diff options
996 files changed, 21749 insertions, 7145 deletions
@@ -3554,12 +3554,12 @@ E: cvance@nai.com D: portions of the Linux Security Module (LSM) framework and security modules N: Petr Vandrovec -E: vandrove@vc.cvut.cz +E: petr@vandrovec.name D: Small contributions to ncpfs D: Matrox framebuffer driver -S: Chudenicka 8 -S: 10200 Prague 10, Hostivar -S: Czech Republic +S: 21513 Conradia Ct +S: Cupertino, CA 95014 +S: USA N: Thibaut Varene E: T-Bone@parisc-linux.org diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 7f5fc3b..ecf7d04 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -6,6 +6,8 @@ Interrupts - ARM Interrupt subsystem documentation IXP2000 - Release Notes for Linux on Intel's IXP2000 Network Processor +msm + - MSM specific documentation Netwinder - Netwinder specific documentation Porting diff --git a/Documentation/arm/msm/gpiomux.txt b/Documentation/arm/msm/gpiomux.txt new file mode 100644 index 0000000..67a8162 --- /dev/null +++ b/Documentation/arm/msm/gpiomux.txt @@ -0,0 +1,176 @@ +This document provides an overview of the msm_gpiomux interface, which +is used to provide gpio pin multiplexing and configuration on mach-msm +targets. + +History +======= + +The first-generation API for gpio configuration & multiplexing on msm +is the function gpio_tlmm_config(). This function has a few notable +shortcomings, which led to its deprecation and replacement by gpiomux: + +The 'disable' parameter: Setting the second parameter to +gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral +processor in charge of the subsystem to perform a look-up into a +low-power table and apply the low-power/sleep setting for the pin. +As the msm family evolved this became problematic. Not all pins +have sleep settings, not all peripheral processors will accept requests +to apply said sleep settings, and not all msm targets have their gpio +subsystems managed by a peripheral processor. In order to get consistent +behavior on all targets, drivers are forced to ignore this parameter, +rendering it useless. + +The 'direction' flag: for all mux-settings other than raw-gpio (0), +the output-enable bit of a gpio is hard-wired to a known +input (usually VDD or ground). For those settings, the direction flag +is meaningless at best, and deceptive at worst. In addition, using the +direction flag to change output-enable (OE) directly can cause trouble in +gpiolib, which has no visibility into gpio direction changes made +in this way. Direction control in gpio mode should be made through gpiolib. + +Key Features of gpiomux +======================= + +- A consistent interface across all generations of msm. Drivers can expect +the same results on every target. +- gpiomux plays nicely with gpiolib. Functions that should belong to gpiolib +are left to gpiolib and not duplicated here. gpiomux is written with the +intent that gpio_chips will call gpiomux reference-counting methods +from their request() and free() hooks, providing full integration. +- Tabular configuration. Instead of having to call gpio_tlmm_config +hundreds of times, gpio configuration is placed in a single table. +- Per-gpio sleep. Each gpio is individually reference counted, allowing only +those lines which are in use to be put in high-power states. +- 0 means 'do nothing': all flags are designed so that the default memset-zero +equates to a sensible default of 'no configuration', preventing users +from having to provide hundreds of 'no-op' configs for unused or +unwanted lines. + +Usage +===== + +To use gpiomux, provide configuration information for relevant gpio lines +in the msm_gpiomux_configs table. Since a 0 equates to "unconfigured", +only those lines to be managed by gpiomux need to be specified. Here +is a completely fictional example: + +struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { + [12] = { + .active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1, + .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN, + }, + [34] = { + .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN, + }, +}; + +To indicate that a gpio is in use, call msm_gpiomux_get() to increase +its reference count. To decrease the reference count, call msm_gpiomux_put(). + +The effect of this configuration is as follows: + +When the system boots, gpios 12 and 34 will be initialized with their +'suspended' configurations. All other gpios, which were left unconfigured, +will not be touched. + +When msm_gpiomux_get() is called on gpio 12 to raise its reference count +above 0, its active configuration will be applied. Since no other gpio +line has a valid active configuration, msm_gpiomux_get() will have no +effect on any other line. + +When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference +count to 0, their suspended configurations will be applied. +Since no other gpio line has a valid suspended configuration, no other +gpio line will be effected by msm_gpiomux_put(). Since gpio 34 has no valid +active configuration, this is effectively a no-op for gpio 34 as well, +with one small caveat, see the section "About Output-Enable Settings". + +All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but +they address some important issues. As unused entries (all those +except 12 and 34) are zero-filled, gpiomux needs a way to distinguish +the used fields from the unused. In addition, the all-zero pattern +is a valid configuration! Therefore, gpiomux defines an additional bit +which is used to indicate when a field is used. This has the pleasant +side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate +that a value should not be changed: + + msm_gpiomux_write(0, GPIOMUX_VALID, 0); + +replaces the active configuration of gpio 0 with an all-zero configuration, +but leaves the suspended configuration as it was. + +Static Configurations +===================== + +To install a static configuration, which is applied at boot and does +not change after that, install a configuration with a suspended component +but no active component, as in the previous example: + + [34] = { + .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN, + }, + +The suspended setting is applied during boot, and the lack of any valid +active setting prevents any other setting from being applied at runtime. +If other subsystems attempting to access the line is a concern, one could +*really* anchor the configuration down by calling msm_gpiomux_get on the +line at initialization to move the line into active mode. With the line +held, it will never be re-suspended, and with no valid active configuration, +no new configurations will be applied. + +But then, if having other subsystems grabbing for the line is truly a concern, +it should be reserved with gpio_request instead, which carries an implicit +msm_gpiomux_get. + +gpiomux and gpiolib +=================== + +It is expected that msm gpio_chips will call msm_gpiomux_get() and +msm_gpiomux_put() from their request and free hooks, like this fictional +example: + +static int request(struct gpio_chip *chip, unsigned offset) +{ + return msm_gpiomux_get(chip->base + offset); +} + +static void free(struct gpio_chip *chip, unsigned offset) +{ + msm_gpiomux_put(chip->base + offset); +} + + ...somewhere in a gpio_chip declaration... + .request = request, + .free = free, + +This provides important functionality: +- It guarantees that a gpio line will have its 'active' config applied + when the line is requested, and will not be suspended while the line + remains requested; and +- It guarantees that gpio-direction settings from gpiolib behave sensibly. + See "About Output-Enable Settings." + +This mechanism allows for "auto-request" of gpiomux lines via gpiolib +when it is suitable. Drivers wishing more exact control are, of course, +free to also use msm_gpiomux_set and msm_gpiomux_get. + +About Output-Enable Settings +============================ + +Some msm targets do not have the ability to query the current gpio +configuration setting. This means that changes made to the output-enable +(OE) bit by gpiolib cannot be consistently detected and preserved by gpiomux. +Therefore, when gpiomux applies a configuration setting, any direction +settings which may have been applied by gpiolib are lost and the default +input settings are re-applied. + +For this reason, drivers should not assume that gpio direction settings +continue to hold if they free and then re-request a gpio. This seems like +common sense - after all, anybody could have obtained the line in the +meantime - but it needs saying. + +This also means that calls to msm_gpiomux_write will reset the OE bit, +which means that if the gpio line is held by a client of gpiolib and +msm_gpiomux_write is called, the direction setting has been lost and +gpiolib's internal state has been broken. +Release gpio lines before reconfiguring them. diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index ff45d1f..48ceabe 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -91,12 +91,11 @@ name The chip name. I2C devices get this attribute created automatically. RO -update_rate The rate at which the chip will update readings. +update_interval The interval at which the chip will update readings. Unit: millisecond RW - Some devices have a variable update rate. This attribute - can be used to change the update rate to the desired - frequency. + Some devices have a variable update rate or interval. + This attribute can be used to change it to the desired value. ************ diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt index 2df7186..d9271e7 100644 --- a/Documentation/networking/e1000.txt +++ b/Documentation/networking/e1000.txt @@ -1,82 +1,35 @@ Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters =============================================================== -September 26, 2006 - +Intel Gigabit Linux driver. +Copyright(c) 1999 - 2010 Intel Corporation. Contents ======== -- In This Release - Identifying Your Adapter -- Building and Installation - Command Line Parameters - Speed and Duplex Configuration - Additional Configurations -- Known Issues - Support - -In This Release -=============== - -This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family -of Adapters. This driver includes support for Itanium(R)2-based systems. - -For questions related to hardware requirements, refer to the documentation -supplied with your Intel PRO/1000 adapter. All hardware requirements listed -apply to use with Linux. - -The following features are now available in supported kernels: - - Native VLANs - - Channel Bonding (teaming) - - SNMP - -Channel Bonding documentation can be found in the Linux kernel source: -/Documentation/networking/bonding.txt - -The driver information previously displayed in the /proc filesystem is not -supported in this release. Alternatively, you can use ethtool (version 1.6 -or later), lspci, and ifconfig to obtain the same information. - -Instructions on updating ethtool can be found in the section "Additional -Configurations" later in this document. - -NOTE: The Intel(R) 82562v 10/100 Network Connection only provides 10/100 -support. - - Identifying Your Adapter ======================== For more information on how to identify your adapter, go to the Adapter & Driver ID Guide at: - http://support.intel.com/support/network/adapter/pro100/21397.htm + http://support.intel.com/support/go/network/adapter/idguide.htm For the latest Intel network drivers for Linux, refer to the following website. In the search field, enter your adapter name or type, or use the networking link on the left to search for your adapter: - http://downloadfinder.intel.com/scripts-df/support_intel.asp - + http://support.intel.com/support/go/network/adapter/home.htm Command Line Parameters ======================= -If the driver is built as a module, the following optional parameters -are used by entering them on the command line with the modprobe command -using this syntax: - - modprobe e1000 [<option>=<VAL1>,<VAL2>,...] - -For example, with two PRO/1000 PCI adapters, entering: - - modprobe e1000 TxDescriptors=80,128 - -loads the e1000 driver with 80 TX descriptors for the first adapter and -128 TX descriptors for the second adapter. - The default value for each parameter is generally the recommended setting, unless otherwise noted. @@ -89,10 +42,6 @@ NOTES: For more information about the AutoNeg, Duplex, and Speed parameters, see the application note at: http://www.intel.com/design/network/applnots/ap450.htm - A descriptor describes a data buffer and attributes related to - the data buffer. This information is accessed by the hardware. - - AutoNeg ------- (Supported only on adapters with copper connections) @@ -106,7 +55,6 @@ Duplex parameters must not be specified. NOTE: Refer to the Speed and Duplex section of this readme for more information on the AutoNeg parameter. - Duplex ------ (Supported only on adapters with copper connections) @@ -119,7 +67,6 @@ set to auto-negotiate, the board auto-detects the correct duplex. If the link partner is forced (either full or half), Duplex defaults to half- duplex. - FlowControl ----------- Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx) @@ -128,16 +75,16 @@ Default Value: Reads flow control settings from the EEPROM This parameter controls the automatic generation(Tx) and response(Rx) to Ethernet PAUSE frames. - InterruptThrottleRate --------------------- (not supported on Intel(R) 82542, 82543 or 82544-based adapters) -Valid Range: 0,1,3,100-100000 (0=off, 1=dynamic, 3=dynamic conservative) +Valid Range: 0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative, + 4=simplified balancing) Default Value: 3 The driver can limit the amount of interrupts per second that the adapter -will generate for incoming packets. It does this by writing a value to the -adapter that is based on the maximum amount of interrupts that the adapter +will generate for incoming packets. It does this by writing a value to the +adapter that is based on the maximum amount of interrupts that the adapter will generate per second. Setting InterruptThrottleRate to a value greater or equal to 100 @@ -146,37 +93,43 @@ per second, even if more packets have come in. This reduces interrupt load on the system and can lower CPU utilization under heavy load, but will increase latency as packets are not processed as quickly. -The default behaviour of the driver previously assumed a static -InterruptThrottleRate value of 8000, providing a good fallback value for -all traffic types,but lacking in small packet performance and latency. -The hardware can handle many more small packets per second however, and +The default behaviour of the driver previously assumed a static +InterruptThrottleRate value of 8000, providing a good fallback value for +all traffic types,but lacking in small packet performance and latency. +The hardware can handle many more small packets per second however, and for this reason an adaptive interrupt moderation algorithm was implemented. Since 7.3.x, the driver has two adaptive modes (setting 1 or 3) in which -it dynamically adjusts the InterruptThrottleRate value based on the traffic +it dynamically adjusts the InterruptThrottleRate value based on the traffic that it receives. After determining the type of incoming traffic in the last -timeframe, it will adjust the InterruptThrottleRate to an appropriate value +timeframe, it will adjust the InterruptThrottleRate to an appropriate value for that traffic. The algorithm classifies the incoming traffic every interval into -classes. Once the class is determined, the InterruptThrottleRate value is -adjusted to suit that traffic type the best. There are three classes defined: +classes. Once the class is determined, the InterruptThrottleRate value is +adjusted to suit that traffic type the best. There are three classes defined: "Bulk traffic", for large amounts of packets of normal size; "Low latency", for small amounts of traffic and/or a significant percentage of small -packets; and "Lowest latency", for almost completely small packets or +packets; and "Lowest latency", for almost completely small packets or minimal traffic. -In dynamic conservative mode, the InterruptThrottleRate value is set to 4000 -for traffic that falls in class "Bulk traffic". If traffic falls in the "Low -latency" or "Lowest latency" class, the InterruptThrottleRate is increased +In dynamic conservative mode, the InterruptThrottleRate value is set to 4000 +for traffic that falls in class "Bulk traffic". If traffic falls in the "Low +latency" or "Lowest latency" class, the InterruptThrottleRate is increased stepwise to 20000. This default mode is suitable for most applications. For situations where low latency is vital such as cluster or grid computing, the algorithm can reduce latency even more when InterruptThrottleRate is set to mode 1. In this mode, which operates -the same as mode 3, the InterruptThrottleRate will be increased stepwise to +the same as mode 3, the InterruptThrottleRate will be increased stepwise to 70000 for traffic in class "Lowest latency". +In simplified mode the interrupt rate is based on the ratio of Tx and +Rx traffic. If the bytes per second rate is approximately equal, the +interrupt rate will drop as low as 2000 interrupts per second. If the +traffic is mostly transmit or mostly receive, the interrupt rate could +be as high as 8000. + Setting InterruptThrottleRate to 0 turns off any interrupt moderation and may improve small packet latency, but is generally not suitable for bulk throughput traffic. @@ -212,8 +165,6 @@ NOTE: When e1000 is loaded with default settings and multiple adapters be platform-specific. If CPU utilization is not a concern, use RX_POLLING (NAPI) and default driver settings. - - RxDescriptors ------------- Valid Range: 80-256 for 82542 and 82543-based adapters @@ -225,15 +176,14 @@ by the driver. Increasing this value allows the driver to buffer more incoming packets, at the expense of increased system memory utilization. Each descriptor is 16 bytes. A receive buffer is also allocated for each -descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending +descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending on the MTU setting. The maximum MTU size is 16110. -NOTE: MTU designates the frame size. It only needs to be set for Jumbo - Frames. Depending on the available system resources, the request - for a higher number of receive descriptors may be denied. In this +NOTE: MTU designates the frame size. It only needs to be set for Jumbo + Frames. Depending on the available system resources, the request + for a higher number of receive descriptors may be denied. In this case, use a lower number. - RxIntDelay ---------- Valid Range: 0-65535 (0=off) @@ -254,7 +204,6 @@ CAUTION: When setting RxIntDelay to a value other than 0, adapters may restoring the network connection. To eliminate the potential for the hang ensure that RxIntDelay is set to 0. - RxAbsIntDelay ------------- (This parameter is supported only on 82540, 82545 and later adapters.) @@ -268,7 +217,6 @@ packet is received within the set amount of time. Proper tuning, along with RxIntDelay, may improve traffic throughput in specific network conditions. - Speed ----- (This parameter is supported only on adapters with copper connections.) @@ -280,7 +228,6 @@ Speed forces the line speed to the specified value in megabits per second partner is set to auto-negotiate, the board will auto-detect the correct speed. Duplex should also be set when Speed is set to either 10 or 100. - TxDescriptors ------------- Valid Range: 80-256 for 82542 and 82543-based adapters @@ -295,6 +242,36 @@ NOTE: Depending on the available system resources, the request for a higher number of transmit descriptors may be denied. In this case, use a lower number. +TxDescriptorStep +---------------- +Valid Range: 1 (use every Tx Descriptor) + 4 (use every 4th Tx Descriptor) + +Default Value: 1 (use every Tx Descriptor) + +On certain non-Intel architectures, it has been observed that intense TX +traffic bursts of short packets may result in an improper descriptor +writeback. If this occurs, the driver will report a "TX Timeout" and reset +the adapter, after which the transmit flow will restart, though data may +have stalled for as much as 10 seconds before it resumes. + +The improper writeback does not occur on the first descriptor in a system +memory cache-line, which is typically 32 bytes, or 4 descriptors long. + +Setting TxDescriptorStep to a value of 4 will ensure that all TX descriptors +are aligned to the start of a system memory cache line, and so this problem +will not occur. + +NOTES: Setting TxDescriptorStep to 4 effectively reduces the number of + TxDescriptors available for transmits to 1/4 of the normal allocation. + This has a possible negative performance impact, which may be + compensated for by allocating more descriptors using the TxDescriptors + module parameter. + + There are other conditions which may result in "TX Timeout", which will + not be resolved by the use of the TxDescriptorStep parameter. As the + issue addressed by this parameter has never been observed on Intel + Architecture platforms, it should not be used on Intel platforms. TxIntDelay ---------- @@ -307,7 +284,6 @@ efficiency if properly tuned for specific network traffic. If the system is reporting dropped transmits, this value may be set too high causing the driver to run out of available transmit descriptors. - TxAbsIntDelay ------------- (This parameter is supported only on 82540, 82545 and later adapters.) @@ -330,6 +306,35 @@ Default Value: 1 A value of '1' indicates that the driver should enable IP checksum offload for received packets (both UDP and TCP) to the adapter hardware. +Copybreak +--------- +Valid Range: 0-xxxxxxx (0=off) +Default Value: 256 +Usage: insmod e1000.ko copybreak=128 + +Driver copies all packets below or equaling this size to a fresh Rx +buffer before handing it up the stack. + +This parameter is different than other parameters, in that it is a +single (not 1,1,1 etc.) parameter applied to all driver instances and +it is also available during runtime at +/sys/module/e1000/parameters/copybreak + +SmartPowerDownEnable +-------------------- +Valid Range: 0-1 +Default Value: 0 (disabled) + +Allows PHY to turn off in lower power states. The user can turn off +this parameter in supported chipsets. + +KumeranLockLoss +--------------- +Valid Range: 0-1 +Default Value: 1 (enabled) + +This workaround skips resetting the PHY at shutdown for the initial +silicon releases of ICH8 systems. Speed and Duplex Configuration ============================== @@ -385,40 +390,9 @@ If the link partner is forced to a specific speed and duplex, then this parameter should not be used. Instead, use the Speed and Duplex parameters previously mentioned to force the adapter to the same speed and duplex. - Additional Configurations ========================= - Configuring the Driver on Different Distributions - ------------------------------------------------- - Configuring a network driver to load properly when the system is started - is distribution dependent. Typically, the configuration process involves - adding an alias line to /etc/modules.conf or /etc/modprobe.conf as well - as editing other system startup scripts and/or configuration files. Many - popular Linux distributions ship with tools to make these changes for you. - To learn the proper way to configure a network device for your system, - refer to your distribution documentation. If during this process you are - asked for the driver or module name, the name for the Linux Base Driver - for the Intel(R) PRO/1000 Family of Adapters is e1000. - - As an example, if you install the e1000 driver for two PRO/1000 adapters - (eth0 and eth1) and set the speed and duplex to 10full and 100half, add - the following to modules.conf or or modprobe.conf: - - alias eth0 e1000 - alias eth1 e1000 - options e1000 Speed=10,100 Duplex=2,1 - - Viewing Link Messages - --------------------- - Link messages will not be displayed to the console if the distribution is - restricting system messages. In order to see network driver link messages - on your console, set dmesg to eight by entering the following: - - dmesg -n 8 - - NOTE: This setting is not saved across reboots. - Jumbo Frames ------------ Jumbo Frames support is enabled by changing the MTU to a value larger than @@ -437,9 +411,11 @@ Additional Configurations setting in a different location. Notes: - - - To enable Jumbo Frames, increase the MTU size on the interface beyond - 1500. + Degradation in throughput performance may be observed in some Jumbo frames + environments. If this is observed, increasing the application's socket buffer + size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values may help. + See the specific application manual and /usr/src/linux*/Documentation/ + networking/ip-sysctl.txt for more details. - The maximum MTU setting for Jumbo Frames is 16110. This value coincides with the maximum Jumbo Frames size of 16128. @@ -447,40 +423,11 @@ Additional Configurations - Using Jumbo Frames at 10 or 100 Mbps may result in poor performance or loss of link. - - Some Intel gigabit adapters that support Jumbo Frames have a frame size - limit of 9238 bytes, with a corresponding MTU size limit of 9216 bytes. - The adapters with this limitation are based on the Intel(R) 82571EB, - 82572EI, 82573L and 80003ES2LAN controller. These correspond to the - following product names: - Intel(R) PRO/1000 PT Server Adapter - Intel(R) PRO/1000 PT Desktop Adapter - Intel(R) PRO/1000 PT Network Connection - Intel(R) PRO/1000 PT Dual Port Server Adapter - Intel(R) PRO/1000 PT Dual Port Network Connection - Intel(R) PRO/1000 PF Server Adapter - Intel(R) PRO/1000 PF Network Connection - Intel(R) PRO/1000 PF Dual Port Server Adapter - Intel(R) PRO/1000 PB Server Connection - Intel(R) PRO/1000 PL Network Connection - Intel(R) PRO/1000 EB Network Connection with I/O Acceleration - Intel(R) PRO/1000 EB Backplane Connection with I/O Acceleration - Intel(R) PRO/1000 PT Quad Port Server Adapter - - Adapters based on the Intel(R) 82542 and 82573V/E controller do not support Jumbo Frames. These correspond to the following product names: Intel(R) PRO/1000 Gigabit Server Adapter Intel(R) PRO/1000 PM Network Connection - - The following adapters do not support Jumbo Frames: - Intel(R) 82562V 10/100 Network Connection - Intel(R) 82566DM Gigabit Network Connection - Intel(R) 82566DC Gigabit Network Connection - Intel(R) 82566MM Gigabit Network Connection - Intel(R) 82566MC Gigabit Network Connection - Intel(R) 82562GT 10/100 Network Connection - Intel(R) 82562G 10/100 Network Connection - - Ethtool ------- The driver utilizes the ethtool interface for driver configuration and @@ -490,142 +437,14 @@ Additional Configurations The latest release of ethtool can be found from http://sourceforge.net/projects/gkernel. - NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support - for a more complete ethtool feature set can be enabled by upgrading - ethtool to ethtool-1.8.1. - Enabling Wake on LAN* (WoL) --------------------------- - WoL is configured through the Ethtool* utility. Ethtool is included with - all versions of Red Hat after Red Hat 7.2. For other Linux distributions, - download and install Ethtool from the following website: - http://sourceforge.net/projects/gkernel. - - For instructions on enabling WoL with Ethtool, refer to the website listed - above. + WoL is configured through the Ethtool* utility. WoL will be enabled on the system during the next shut down or reboot. For this driver version, in order to enable WoL, the e1000 driver must be loaded when shutting down or rebooting the system. - Wake On LAN is only supported on port A for the following devices: - Intel(R) PRO/1000 PT Dual Port Network Connection - Intel(R) PRO/1000 PT Dual Port Server Connection - Intel(R) PRO/1000 PT Dual Port Server Adapter - Intel(R) PRO/1000 PF Dual Port Server Adapter - Intel(R) PRO/1000 PT Quad Port Server Adapter - - NAPI - ---- - NAPI (Rx polling mode) is enabled in the e1000 driver. - - See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI. - - -Known Issues -============ - -Dropped Receive Packets on Half-duplex 10/100 Networks ------------------------------------------------------- -If you have an Intel PCI Express adapter running at 10mbps or 100mbps, half- -duplex, you may observe occasional dropped receive packets. There are no -workarounds for this problem in this network configuration. The network must -be updated to operate in full-duplex, and/or 1000mbps only. - -Jumbo Frames System Requirement -------------------------------- -Memory allocation failures have been observed on Linux systems with 64 MB -of RAM or less that are running Jumbo Frames. If you are using Jumbo -Frames, your system may require more than the advertised minimum -requirement of 64 MB of system memory. - -Performance Degradation with Jumbo Frames ------------------------------------------ -Degradation in throughput performance may be observed in some Jumbo frames -environments. If this is observed, increasing the application's socket -buffer size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values -may help. See the specific application manual and -/usr/src/linux*/Documentation/ -networking/ip-sysctl.txt for more details. - -Jumbo Frames on Foundry BigIron 8000 switch -------------------------------------------- -There is a known issue using Jumbo frames when connected to a Foundry -BigIron 8000 switch. This is a 3rd party limitation. If you experience -loss of packets, lower the MTU size. - -Allocating Rx Buffers when Using Jumbo Frames ---------------------------------------------- -Allocating Rx buffers when using Jumbo Frames on 2.6.x kernels may fail if -the available memory is heavily fragmented. This issue may be seen with PCI-X -adapters or with packet split disabled. This can be reduced or eliminated -by changing the amount of available memory for receive buffer allocation, by -increasing /proc/sys/vm/min_free_kbytes. - -Multiple Interfaces on Same Ethernet Broadcast Network ------------------------------------------------------- -Due to the default ARP behavior on Linux, it is not possible to have -one system on two IP networks in the same Ethernet broadcast domain -(non-partitioned switch) behave as expected. All Ethernet interfaces -will respond to IP traffic for any IP address assigned to the system. -This results in unbalanced receive traffic. - -If you have multiple interfaces in a server, either turn on ARP -filtering by entering: - - echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter -(this only works if your kernel's version is higher than 2.4.5), - -NOTE: This setting is not saved across reboots. The configuration -change can be made permanent by adding the line: - net.ipv4.conf.all.arp_filter = 1 -to the file /etc/sysctl.conf - - or, - -install the interfaces in separate broadcast domains (either in -different switches or in a switch partitioned to VLANs). - -82541/82547 can't link or are slow to link with some link partners ------------------------------------------------------------------ -There is a known compatibility issue with 82541/82547 and some -low-end switches where the link will not be established, or will -be slow to establish. In particular, these switches are known to -be incompatible with 82541/82547: - - Planex FXG-08TE - I-O Data ETG-SH8 - -To workaround this issue, the driver can be compiled with an override -of the PHY's master/slave setting. Forcing master or forcing slave -mode will improve time-to-link. - - # make CFLAGS_EXTRA=-DE1000_MASTER_SLAVE=<n> - -Where <n> is: - - 0 = Hardware default - 1 = Master mode - 2 = Slave mode - 3 = Auto master/slave - -Disable rx flow control with ethtool ------------------------------------- -In order to disable receive flow control using ethtool, you must turn -off auto-negotiation on the same command line. - -For example: - - ethtool -A eth? autoneg off rx off - -Unplugging network cable while ethtool -p is running ----------------------------------------------------- -In kernel versions 2.5.50 and later (including 2.6 kernel), unplugging -the network cable while ethtool -p is running will cause the system to -become unresponsive to keyboard commands, except for control-alt-delete. -Restarting the system appears to be the only remedy. - - Support ======= diff --git a/Documentation/networking/e1000e.txt b/Documentation/networking/e1000e.txt new file mode 100644 index 0000000..6aa048b --- /dev/null +++ b/Documentation/networking/e1000e.txt @@ -0,0 +1,302 @@ +Linux* Driver for Intel(R) Network Connection +=============================================================== + +Intel Gigabit Linux driver. +Copyright(c) 1999 - 2010 Intel Corporation. + +Contents +======== + +- Identifying Your Adapter +- Command Line Parameters +- Additional Configurations +- Support + +Identifying Your Adapter +======================== + +The e1000e driver supports all PCI Express Intel(R) Gigabit Network +Connections, except those that are 82575, 82576 and 82580-based*. + +* NOTE: The Intel(R) PRO/1000 P Dual Port Server Adapter is supported by + the e1000 driver, not the e1000e driver due to the 82546 part being used + behind a PCI Express bridge. + +For more information on how to identify your adapter, go to the Adapter & +Driver ID Guide at: + + http://support.intel.com/support/go/network/adapter/idguide.htm + +For the latest Intel network drivers for Linux, refer to the following +website. In the search field, enter your adapter name or type, or use the +networking link on the left to search for your adapter: + + http://support.intel.com/support/go/network/adapter/home.htm + +Command Line Parameters +======================= + +The default value for each parameter is generally the recommended setting, +unless otherwise noted. + +NOTES: For more information about the InterruptThrottleRate, + RxIntDelay, TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay + parameters, see the application note at: + http://www.intel.com/design/network/applnots/ap450.htm + +InterruptThrottleRate +--------------------- +Valid Range: 0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative, + 4=simplified balancing) +Default Value: 3 + +The driver can limit the amount of interrupts per second that the adapter +will generate for incoming packets. It does this by writing a value to the +adapter that is based on the maximum amount of interrupts that the adapter +will generate per second. + +Setting InterruptThrottleRate to a value greater or equal to 100 +will program the adapter to send out a maximum of that many interrupts +per second, even if more packets have come in. This reduces interrupt +load on the system and can lower CPU utilization under heavy load, +but will increase latency as packets are not processed as quickly. + +The driver has two adaptive modes (setting 1 or 3) in which +it dynamically adjusts the InterruptThrottleRate value based on the traffic +that it receives. After determining the type of incoming traffic in the last +timeframe, it will adjust the InterruptThrottleRate to an appropriate value +for that traffic. + +The algorithm classifies the incoming traffic every interval into +classes. Once the class is determined, the InterruptThrottleRate value is +adjusted to suit that traffic type the best. There are three classes defined: +"Bulk traffic", for large amounts of packets of normal size; "Low latency", +for small amounts of traffic and/or a significant percentage of small +packets; and "Lowest latency", for almost completely small packets or +minimal traffic. + +In dynamic conservative mode, the InterruptThrottleRate value is set to 4000 +for traffic that falls in class "Bulk traffic". If traffic falls in the "Low +latency" or "Lowest latency" class, the InterruptThrottleRate is increased +stepwise to 20000. This default mode is suitable for most applications. + +For situations where low latency is vital such as cluster or +grid computing, the algorithm can reduce latency even more when +InterruptThrottleRate is set to mode 1. In this mode, which operates +the same as mode 3, the InterruptThrottleRate will be increased stepwise to +70000 for traffic in class "Lowest latency". + +In simplified mode the interrupt rate is based on the ratio of Tx and +Rx traffic. If the bytes per second rate is approximately equal the +interrupt rate will drop as low as 2000 interrupts per second. If the +traffic is mostly transmit or mostly receive, the interrupt rate could +be as high as 8000. + +Setting InterruptThrottleRate to 0 turns off any interrupt moderation +and may improve small packet latency, but is generally not suitable +for bulk throughput traffic. + +NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and + RxAbsIntDelay parameters. In other words, minimizing the receive + and/or transmit absolute delays does not force the controller to + generate more interrupts than what the Interrupt Throttle Rate + allows. + +NOTE: When e1000e is loaded with default settings and multiple adapters + are in use simultaneously, the CPU utilization may increase non- + linearly. In order to limit the CPU utilization without impacting + the overall throughput, we recommend that you load the driver as + follows: + + modprobe e1000e InterruptThrottleRate=3000,3000,3000 + + This sets the InterruptThrottleRate to 3000 interrupts/sec for + the first, second, and third instances of the driver. The range + of 2000 to 3000 interrupts per second works on a majority of + systems and is a good starting point, but the optimal value will + be platform-specific. If CPU utilization is not a concern, use + RX_POLLING (NAPI) and default driver settings. + +RxIntDelay +---------- +Valid Range: 0-65535 (0=off) +Default Value: 0 + +This value delays the generation of receive interrupts in units of 1.024 +microseconds. Receive interrupt reduction can improve CPU efficiency if +properly tuned for specific network traffic. Increasing this value adds +extra latency to frame reception and can end up decreasing the throughput +of TCP traffic. If the system is reporting dropped receives, this value +may be set too high, causing the driver to run out of available receive +descriptors. + +CAUTION: When setting RxIntDelay to a value other than 0, adapters may + hang (stop transmitting) under certain network conditions. If + this occurs a NETDEV WATCHDOG message is logged in the system + event log. In addition, the controller is automatically reset, + restoring the network connection. To eliminate the potential + for the hang ensure that RxIntDelay is set to 0. + +RxAbsIntDelay +------------- +Valid Range: 0-65535 (0=off) +Default Value: 8 + +This value, in units of 1.024 microseconds, limits the delay in which a +receive interrupt is generated. Useful only if RxIntDelay is non-zero, +this value ensures that an interrupt is generated after the initial +packet is received within the set amount of time. Proper tuning, +along with RxIntDelay, may improve traffic throughput in specific network +conditions. + +TxIntDelay +---------- +Valid Range: 0-65535 (0=off) +Default Value: 8 + +This value delays the generation of transmit interrupts in units of +1.024 microseconds. Transmit interrupt reduction can improve CPU +efficiency if properly tuned for specific network traffic. If the +system is reporting dropped transmits, this value may be set too high +causing the driver to run out of available transmit descriptors. + +TxAbsIntDelay +------------- +Valid Range: 0-65535 (0=off) +Default Value: 32 + +This value, in units of 1.024 microseconds, limits the delay in which a +transmit interrupt is generated. Useful only if TxIntDelay is non-zero, +this value ensures that an interrupt is generated after the initial +packet is sent on the wire within the set amount of time. Proper tuning, +along with TxIntDelay, may improve traffic throughput in specific +network conditions. + +Copybreak +--------- +Valid Range: 0-xxxxxxx (0=off) +Default Value: 256 + +Driver copies all packets below or equaling this size to a fresh Rx +buffer before handing it up the stack. + +This parameter is different than other parameters, in that it is a +single (not 1,1,1 etc.) parameter applied to all driver instances and +it is also available during runtime at +/sys/module/e1000e/parameters/copybreak + +SmartPowerDownEnable +-------------------- +Valid Range: 0-1 +Default Value: 0 (disabled) + +Allows PHY to turn off in lower power states. The user can set this parameter +in supported chipsets. + +KumeranLockLoss +--------------- +Valid Range: 0-1 +Default Value: 1 (enabled) + +This workaround skips resetting the PHY at shutdown for the initial +silicon releases of ICH8 systems. + +IntMode +------- +Valid Range: 0-2 (0=legacy, 1=MSI, 2=MSI-X) +Default Value: 2 + +Allows changing the interrupt mode at module load time, without requiring a +recompile. If the driver load fails to enable a specific interrupt mode, the +driver will try other interrupt modes, from least to most compatible. The +interrupt order is MSI-X, MSI, Legacy. If specifying MSI (IntMode=1) +interrupts, only MSI and Legacy will be attempted. + +CrcStripping +------------ +Valid Range: 0-1 +Default Value: 1 (enabled) + +Strip the CRC from received packets before sending up the network stack. If +you have a machine with a BMC enabled but cannot receive IPMI traffic after +loading or enabling the driver, try disabling this feature. + +WriteProtectNVM +--------------- +Valid Range: 0-1 +Default Value: 1 (enabled) + +Set the hardware to ignore all write/erase cycles to the GbE region in the +ICHx NVM (non-volatile memory). This feature can be disabled by the +WriteProtectNVM module parameter (enabled by default) only after a hardware +reset, but the machine must be power cycled before trying to enable writes. + +Note: the kernel boot option iomem=relaxed may need to be set if the kernel +config option CONFIG_STRICT_DEVMEM=y, if the root user wants to write the +NVM from user space via ethtool. + +Additional Configurations +========================= + + Jumbo Frames + ------------ + Jumbo Frames support is enabled by changing the MTU to a value larger than + the default of 1500. Use the ifconfig command to increase the MTU size. + For example: + + ifconfig eth<x> mtu 9000 up + + This setting is not saved across reboots. + + Notes: + + - The maximum MTU setting for Jumbo Frames is 9216. This value coincides + with the maximum Jumbo Frames size of 9234 bytes. + + - Using Jumbo Frames at 10 or 100 Mbps is not supported and may result in + poor performance or loss of link. + + - Some adapters limit Jumbo Frames sized packets to a maximum of + 4096 bytes and some adapters do not support Jumbo Frames. + + + Ethtool + ------- + The driver utilizes the ethtool interface for driver configuration and + diagnostics, as well as displaying statistical information. We + strongly recommend downloading the latest version of Ethtool at: + + http://sourceforge.net/projects/gkernel. + + Speed and Duplex + ---------------- + Speed and Duplex are configured through the Ethtool* utility. For + instructions, refer to the Ethtool man page. + + Enabling Wake on LAN* (WoL) + --------------------------- + WoL is configured through the Ethtool* utility. For instructions on + enabling WoL with Ethtool, refer to the Ethtool man page. + + WoL will be enabled on the system during the next shut down or reboot. + For this driver version, in order to enable WoL, the e1000e driver must be + loaded when shutting down or rebooting the system. + + In most cases Wake On LAN is only supported on port A for multiple port + adapters. To verify if a port supports Wake on LAN run ethtool eth<X>. + + +Support +======= + +For general information, go to the Intel support website at: + + www.intel.com/support/ + +or the Intel Wired Networking project hosted by Sourceforge at: + + http://sourceforge.net/projects/e1000 + +If an issue is identified with the released source code on the supported +kernel with a supported adapter, email the specific information related +to the issue to e1000-devel@lists.sf.net diff --git a/Documentation/networking/ixgbevf.txt b/Documentation/networking/ixgbevf.txt index 19015de..21dd5d1 100755..100644 --- a/Documentation/networking/ixgbevf.txt +++ b/Documentation/networking/ixgbevf.txt @@ -1,19 +1,16 @@ Linux* Base Driver for Intel(R) Network Connection ================================================== -November 24, 2009 +Intel Gigabit Linux driver. +Copyright(c) 1999 - 2010 Intel Corporation. Contents ======== -- In This Release - Identifying Your Adapter - Known Issues/Troubleshooting - Support -In This Release -=============== - This file describes the ixgbevf Linux* Base Driver for Intel Network Connection. @@ -33,7 +30,7 @@ Identifying Your Adapter For more information on how to identify your adapter, go to the Adapter & Driver ID Guide at: - http://support.intel.com/support/network/sb/CS-008441.htm + http://support.intel.com/support/go/network/adapter/idguide.htm Known Issues/Troubleshooting ============================ @@ -57,34 +54,3 @@ or the Intel Wired Networking project hosted by Sourceforge at: If an issue is identified with the released source code on the supported kernel with a supported adapter, email the specific information related to the issue to e1000-devel@lists.sf.net - -License -======= - -Intel 10 Gigabit Linux driver. -Copyright(c) 1999 - 2009 Intel Corporation. - -This program is free software; you can redistribute it and/or modify it -under the terms and conditions of the GNU General Public License, -version 2, as published by the Free Software Foundation. - -This program is distributed in the hope it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - -The full GNU General Public License is included in this distribution in -the file called "COPYING". - -Trademarks -========== - -Intel, Itanium, and Pentium are trademarks or registered trademarks of -Intel Corporation or its subsidiaries in the United States and other -countries. - -* Other names and brands may be claimed as the property of others. diff --git a/Documentation/power/regulator/overview.txt b/Documentation/power/regulator/overview.txt index 9363e05..8ed1758 100644 --- a/Documentation/power/regulator/overview.txt +++ b/Documentation/power/regulator/overview.txt @@ -13,7 +13,7 @@ regulators (where voltage output is controllable) and current sinks (where current limit is controllable). (C) 2008 Wolfson Microelectronics PLC. -Author: Liam Girdwood <lg@opensource.wolfsonmicro.com> +Author: Liam Girdwood <lrg@slimlogic.co.uk> Nomenclature diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c index ccd951f..cc96ee2 100644 --- a/Documentation/vm/page-types.c +++ b/Documentation/vm/page-types.c @@ -478,7 +478,7 @@ static void prepare_hwpoison_fd(void) } if (opt_unpoison && !hwpoison_forget_fd) { - sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs); + sprintf(buf, "%s/unpoison-pfn", hwpoison_debug_fs); hwpoison_forget_fd = checked_open(buf, O_WRONLY); } } diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt new file mode 100644 index 0000000..e4498a2 --- /dev/null +++ b/Documentation/workqueue.txt @@ -0,0 +1,380 @@ + +Concurrency Managed Workqueue (cmwq) + +September, 2010 Tejun Heo <tj@kernel.org> + Florian Mickler <florian@mickler.org> + +CONTENTS + +1. Introduction +2. Why cmwq? +3. The Design +4. Application Programming Interface (API) +5. Example Execution Scenarios +6. Guidelines + + +1. Introduction + +There are many cases where an asynchronous process execution context +is needed and the workqueue (wq) API is the most commonly used +mechanism for such cases. + +When such an asynchronous execution context is needed, a work item +describing which function to execute is put on a queue. An +independent thread serves as the asynchronous execution context. The +queue is called workqueue and the thread is called worker. + +While there are work items on the workqueue the worker executes the +functions associated with the work items one after the other. When +there is no work item left on the workqueue the worker becomes idle. +When a new work item gets queued, the worker begins executing again. + + +2. Why cmwq? + +In the original wq implementation, a multi threaded (MT) wq had one +worker thread per CPU and a single threaded (ST) wq had one worker +thread system-wide. A single MT wq needed to keep around the same +number of workers as the number of CPUs. The kernel grew a lot of MT +wq users over the years and with the number of CPU cores continuously +rising, some systems saturated the default 32k PID space just booting +up. + +Although MT wq wasted a lot of resource, the level of concurrency +provided was unsatisfactory. The limitation was common to both ST and +MT wq albeit less severe on MT. Each wq maintained its own separate +worker pool. A MT wq could provide only one execution context per CPU +while a ST wq one for the whole system. Work items had to compete for +those very limited execution contexts leading to various problems +including proneness to deadlocks around the single execution context. + +The tension between the provided level of concurrency and resource +usage also forced its users to make unnecessary tradeoffs like libata +choosing to use ST wq for polling PIOs and accepting an unnecessary +limitation that no two polling PIOs can progress at the same time. As +MT wq don't provide much better concurrency, users which require +higher level of concurrency, like async or fscache, had to implement +their own thread pool. + +Concurrency Managed Workqueue (cmwq) is a reimplementation of wq with +focus on the following goals. + +* Maintain compatibility with the original workqueue API. + +* Use per-CPU unified worker pools shared by all wq to provide + flexible level of concurrency on demand without wasting a lot of + resource. + +* Automatically regulate worker pool and level of concurrency so that + the API users don't need to worry about such details. + + +3. The Design + +In order to ease the asynchronous execution of functions a new +abstraction, the work item, is introduced. + +A work item is a simple struct that holds a pointer to the function +that is to be executed asynchronously. Whenever a driver or subsystem +wants a function to be executed asynchronously it has to set up a work +item pointing to that function and queue that work item on a +workqueue. + +Special purpose threads, called worker threads, execute the functions +off of the queue, one after the other. If no work is queued, the +worker threads become idle. These worker threads are managed in so +called thread-pools. + +The cmwq design differentiates between the user-facing workqueues that +subsystems and drivers queue work items on and the backend mechanism +which manages thread-pool and processes the queued work items. + +The backend is called gcwq. There is one gcwq for each possible CPU +and one gcwq to serve work items queued on unbound workqueues. + +Subsystems and drivers can create and queue work items through special +workqueue API functions as they see fit. They can influence some +aspects of the way the work items are executed by setting flags on the +workqueue they are putting the work item on. These flags include +things like CPU locality, reentrancy, concurrency limits and more. To +get a detailed overview refer to the API description of +alloc_workqueue() below. + +When a work item is queued to a workqueue, the target gcwq is +determined according to the queue parameters and workqueue attributes +and appended on the shared worklist of the gcwq. For example, unless +specifically overridden, a work item of a bound workqueue will be +queued on the worklist of exactly that gcwq that is associated to the +CPU the issuer is running on. + +For any worker pool implementation, managing the concurrency level +(how many execution contexts are active) is an important issue. cmwq +tries to keep the concurrency at a minimal but sufficient level. +Minimal to save resources and sufficient in that the system is used at +its full capacity. + +Each gcwq bound to an actual CPU implements concurrency management by +hooking into the scheduler. The gcwq is notified whenever an active +worker wakes up or sleeps and keeps track of the number of the +currently runnable workers. Generally, work items are not expected to +hog a CPU and consume many cycles. That means maintaining just enough +concurrency to prevent work processing from stalling should be +optimal. As long as there are one or more runnable workers on the +CPU, the gcwq doesn't start execution of a new work, but, when the +last running worker goes to sleep, it immediately schedules a new +worker so that the CPU doesn't sit idle while there are pending work +items. This allows using a minimal number of workers without losing +execution bandwidth. + +Keeping idle workers around doesn't cost other than the memory space +for kthreads, so cmwq holds onto idle ones for a while before killing +them. + +For an unbound wq, the above concurrency management doesn't apply and +the gcwq for the pseudo unbound CPU tries to start executing all work +items as soon as possible. The responsibility of regulating +concurrency level is on the users. There is also a flag to mark a +bound wq to ignore the concurrency management. Please refer to the +API section for details. + +Forward progress guarantee relies on that workers can be created when +more execution contexts are necessary, which in turn is guaranteed +through the use of rescue workers. All work items which might be used +on code paths that handle memory reclaim are required to be queued on +wq's that have a rescue-worker reserved for execution under memory +pressure. Else it is possible that the thread-pool deadlocks waiting +for execution contexts to free up. + + +4. Application Programming Interface (API) + +alloc_workqueue() allocates a wq. The original create_*workqueue() +functions are deprecated and scheduled for removal. alloc_workqueue() +takes three arguments - @name, @flags and @max_active. @name is the +name of the wq and also used as the name of the rescuer thread if +there is one. + +A wq no longer manages execution resources but serves as a domain for +forward progress guarantee, flush and work item attributes. @flags +and @max_active control how work items are assigned execution +resources, scheduled and executed. + +@flags: + + WQ_NON_REENTRANT + + By default, a wq guarantees non-reentrance only on the same + CPU. A work item may not be executed concurrently on the same + CPU by multiple workers but is allowed to be executed + concurrently on multiple CPUs. This flag makes sure + non-reentrance is enforced across all CPUs. Work items queued + to a non-reentrant wq are guaranteed to be executed by at most + one worker system-wide at any given time. + + WQ_UNBOUND + + Work items queued to an unbound wq are served by a special + gcwq which hosts workers which are not bound to any specific + CPU. This makes the wq behave as a simple execution context + provider without concurrency management. The unbound gcwq + tries to start execution of work items as soon as possible. + Unbound wq sacrifices locality but is useful for the following + cases. + + * Wide fluctuation in the concurrency level requirement is + expected and using bound wq may end up creating large number + of mostly unused workers across different CPUs as the issuer + hops through different CPUs. + + * Long running CPU intensive workloads which can be better + managed by the system scheduler. + + WQ_FREEZEABLE + + A freezeable wq participates in the freeze phase of the system + suspend operations. Work items on the wq are drained and no + new work item starts execution until thawed. + + WQ_RESCUER + + All wq which might be used in the memory reclaim paths _MUST_ + have this flag set. This reserves one worker exclusively for + the execution of this wq under memory pressure. + + WQ_HIGHPRI + + Work items of a highpri wq are queued at the head of the + worklist of the target gcwq and start execution regardless of + the current concurrency level. In other words, highpri work + items will always start execution as soon as execution + resource is available. + + Ordering among highpri work items is preserved - a highpri + work item queued after another highpri work item will start + execution after the earlier highpri work item starts. + + Although highpri work items are not held back by other + runnable work items, they still contribute to the concurrency + level. Highpri work items in runnable state will prevent + non-highpri work items from starting execution. + + This flag is meaningless for unbound wq. + + WQ_CPU_INTENSIVE + + Work items of a CPU intensive wq do not contribute to the + concurrency level. In other words, runnable CPU intensive + work items will not prevent other work items from starting + execution. This is useful for bound work items which are + expected to hog CPU cycles so that their execution is + regulated by the system scheduler. + + Although CPU intensive work items don't contribute to the + concurrency level, start of their executions is still + regulated by the concurrency management and runnable + non-CPU-intensive work items can delay execution of CPU + intensive work items. + + This flag is meaningless for unbound wq. + + WQ_HIGHPRI | WQ_CPU_INTENSIVE + + This combination makes the wq avoid interaction with + concurrency management completely and behave as a simple + per-CPU execution context provider. Work items queued on a + highpri CPU-intensive wq start execution as soon as resources + are available and don't affect execution of other work items. + +@max_active: + +@max_active determines the maximum number of execution contexts per +CPU which can be assigned to the work items of a wq. For example, +with @max_active of 16, at most 16 work items of the wq can be +executing at the same time per CPU. + +Currently, for a bound wq, the maximum limit for @max_active is 512 +and the default value used when 0 is specified is 256. For an unbound +wq, the limit is higher of 512 and 4 * num_possible_cpus(). These +values are chosen sufficiently high such that they are not the +limiting factor while providing protection in runaway cases. + +The number of active work items of a wq is usually regulated by the +users of the wq, more specifically, by how many work items the users +may queue at the same time. Unless there is a specific need for +throttling the number of active work items, specifying '0' is +recommended. + +Some users depend on the strict execution ordering of ST wq. The +combination of @max_active of 1 and WQ_UNBOUND is used to achieve this +behavior. Work items on such wq are always queued to the unbound gcwq +and only one work item can be active at any given time thus achieving +the same ordering property as ST wq. + + +5. Example Execution Scenarios + +The following example execution scenarios try to illustrate how cmwq +behave under different configurations. + + Work items w0, w1, w2 are queued to a bound wq q0 on the same CPU. + w0 burns CPU for 5ms then sleeps for 10ms then burns CPU for 5ms + again before finishing. w1 and w2 burn CPU for 5ms then sleep for + 10ms. + +Ignoring all other tasks, works and processing overhead, and assuming +simple FIFO scheduling, the following is one highly simplified version +of possible sequences of events with the original wq. + + TIME IN MSECS EVENT + 0 w0 starts and burns CPU + 5 w0 sleeps + 15 w0 wakes up and burns CPU + 20 w0 finishes + 20 w1 starts and burns CPU + 25 w1 sleeps + 35 w1 wakes up and finishes + 35 w2 starts and burns CPU + 40 w2 sleeps + 50 w2 wakes up and finishes + +And with cmwq with @max_active >= 3, + + TIME IN MSECS EVENT + 0 w0 starts and burns CPU + 5 w0 sleeps + 5 w1 starts and burns CPU + 10 w1 sleeps + 10 w2 starts and burns CPU + 15 w2 sleeps + 15 w0 wakes up and burns CPU + 20 w0 finishes + 20 w1 wakes up and finishes + 25 w2 wakes up and finishes + +If @max_active == 2, + + TIME IN MSECS EVENT + 0 w0 starts and burns CPU + 5 w0 sleeps + 5 w1 starts and burns CPU + 10 w1 sleeps + 15 w0 wakes up and burns CPU + 20 w0 finishes + 20 w1 wakes up and finishes + 20 w2 starts and burns CPU + 25 w2 sleeps + 35 w2 wakes up and finishes + +Now, let's assume w1 and w2 are queued to a different wq q1 which has +WQ_HIGHPRI set, + + TIME IN MSECS EVENT + 0 w1 and w2 start and burn CPU + 5 w1 sleeps + 10 w2 sleeps + 10 w0 starts and burns CPU + 15 w0 sleeps + 15 w1 wakes up and finishes + 20 w2 wakes up and finishes + 25 w0 wakes up and burns CPU + 30 w0 finishes + +If q1 has WQ_CPU_INTENSIVE set, + + TIME IN MSECS EVENT + 0 w0 starts and burns CPU + 5 w0 sleeps + 5 w1 and w2 start and burn CPU + 10 w1 sleeps + 15 w2 sleeps + 15 w0 wakes up and burns CPU + 20 w0 finishes + 20 w1 wakes up and finishes + 25 w2 wakes up and finishes + + +6. Guidelines + +* Do not forget to use WQ_RESCUER if a wq may process work items which + are used during memory reclaim. Each wq with WQ_RESCUER set has one + rescuer thread reserved for it. If there is dependency among + multiple work items used during memory reclaim, they should be + queued to separate wq each with WQ_RESCUER. + +* Unless strict ordering is required, there is no need to use ST wq. + +* Unless there is a specific need, using 0 for @max_active is + recommended. In most use cases, concurrency level usually stays + well under the default limit. + +* A wq serves as a domain for forward progress guarantee (WQ_RESCUER), + flush and work item attributes. Work items which are not involved + in memory reclaim and don't need to be flushed as a part of a group + of work items, and don't require any special attribute, can use one + of the system wq. There is no difference in execution + characteristics between using a dedicated wq and a system wq. + +* Unless work items are expected to consume a huge amount of CPU + cycles, using a bound wq is usually beneficial due to the increased + level of locality in wq operations and work item execution. diff --git a/MAINTAINERS b/MAINTAINERS index e7c528f..8395f2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -962,6 +962,23 @@ W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c6410/ +ARM/S5P ARM ARCHITECTURES +M: Kukjin Kim <kgene.kim@samsung.com> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-s5p*/ + +ARM/SAMSUNG S5P SERIES FIMC SUPPORT +M: Kyungmin Park <kyungmin.park@samsung.com> +M: Sylwester Nawrocki <s.nawrocki@samsung.com> +L: linux-arm-kernel@lists.infradead.org +L: linux-media@vger.kernel.org +S: Maintained +F: arch/arm/plat-s5p/dev-fimc* +F: arch/arm/plat-samsung/include/plat/*fimc* +F: drivers/media/video/s5p-fimc/ + ARM/SHMOBILE ARM ARCHITECTURE M: Paul Mundt <lethal@linux-sh.org> M: Magnus Damm <magnus.damm@gmail.com> @@ -973,11 +990,23 @@ S: Supported F: arch/arm/mach-shmobile/ F: drivers/sh/ +ARM/TELECHIPS ARM ARCHITECTURE +M: "Hans J. Koch" <hjk@linutronix.de> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/plat-tcc/ +F: arch/arm/mach-tcc8k/ + ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT M: Lennert Buytenhek <kernel@wantstofly.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained +ARM/TETON BGA MACHINE SUPPORT +M: Mark F. Brown <mark.brown314@gmail.com> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained + ARM/THECUS N2100 MACHINE SUPPORT M: Lennert Buytenhek <kernel@wantstofly.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -1135,7 +1164,7 @@ ATLX ETHERNET DRIVERS M: Jay Cliburn <jcliburn@gmail.com> M: Chris Snook <chris.snook@gmail.com> M: Jie Yang <jie.yang@atheros.com> -L: atl1-devel@lists.sourceforge.net +L: netdev@vger.kernel.org W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net S: Maintained @@ -1220,7 +1249,7 @@ F: drivers/auxdisplay/ F: include/linux/cfag12864b.h AVR32 ARCHITECTURE -M: Haavard Skinnemoen <hskinnemoen@atmel.com> +M: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com> W: http://www.atmel.com/products/AVR32/ W: http://avr32linux.org/ W: http://avrfreaks.net/ @@ -1228,7 +1257,7 @@ S: Supported F: arch/avr32/ AVR32/AT32AP MACHINE SUPPORT -M: Haavard Skinnemoen <hskinnemoen@atmel.com> +M: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com> S: Supported F: arch/avr32/mach-at32ap/ @@ -2199,6 +2228,12 @@ W: http://acpi4asus.sf.net S: Maintained F: drivers/platform/x86/eeepc-laptop.c +EFIFB FRAMEBUFFER DRIVER +L: linux-fbdev@vger.kernel.org +M: Peter Jones <pjones@redhat.com> +S: Maintained +F: drivers/video/efifb.c + EFS FILESYSTEM W: http://aeschi.ch.eu.org/efs/ S: Orphan @@ -2522,7 +2557,7 @@ S: Supported F: drivers/scsi/gdt* GENERIC GPIO I2C DRIVER -M: Haavard Skinnemoen <hskinnemoen@atmel.com> +M: Haavard Skinnemoen <hskinnemoen@gmail.com> S: Supported F: drivers/i2c/busses/i2c-gpio.c F: include/linux/i2c-gpio.h @@ -2657,9 +2692,14 @@ S: Maintained F: drivers/media/video/gspca/ HARDWARE MONITORING +M: Jean Delvare <khali@linux-fr.org> +M: Guenter Roeck <guenter.roeck@ericsson.com> L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ -S: Orphan +T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/ +T: quilt kernel.org/pub/linux/kernel/people/groeck/linux-staging/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git +S: Maintained F: Documentation/hwmon/ F: drivers/hwmon/ F: include/linux/hwmon*.h @@ -3045,16 +3085,27 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ixp2000/ -INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe) +INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf) M: Jeff Kirsher <jeffrey.t.kirsher@intel.com> M: Jesse Brandeburg <jesse.brandeburg@intel.com> M: Bruce Allan <bruce.w.allan@intel.com> -M: Alex Duyck <alexander.h.duyck@intel.com> +M: Carolyn Wyborny <carolyn.wyborny@intel.com> +M: Don Skidmore <donald.c.skidmore@intel.com> +M: Greg Rose <gregory.v.rose@intel.com> M: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com> +M: Alex Duyck <alexander.h.duyck@intel.com> M: John Ronciak <john.ronciak@intel.com> L: e1000-devel@lists.sourceforge.net W: http://e1000.sourceforge.net/ S: Supported +F: Documentation/networking/e100.txt +F: Documentation/networking/e1000.txt +F: Documentation/networking/e1000e.txt +F: Documentation/networking/igb.txt +F: Documentation/networking/igbvf.txt +F: Documentation/networking/ixgb.txt +F: Documentation/networking/ixgbe.txt +F: Documentation/networking/ixgbevf.txt F: drivers/net/e100.c F: drivers/net/e1000/ F: drivers/net/e1000e/ @@ -3062,6 +3113,7 @@ F: drivers/net/igb/ F: drivers/net/igbvf/ F: drivers/net/ixgb/ F: drivers/net/ixgbe/ +F: drivers/net/ixgbevf/ INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT L: linux-wireless@vger.kernel.org @@ -3770,9 +3822,8 @@ W: http://www.syskonnect.com S: Supported MATROX FRAMEBUFFER DRIVER -M: Petr Vandrovec <vandrove@vc.cvut.cz> L: linux-fbdev@vger.kernel.org -S: Maintained +S: Orphan F: drivers/video/matrox/matroxfb_* F: include/linux/matroxfb.h @@ -3896,10 +3947,8 @@ F: Documentation/serial/moxa-smartio F: drivers/char/mxser.* MSI LAPTOP SUPPORT -M: Lennart Poettering <mzxreary@0pointer.de> +M: Lee, Chun-Yi <jlee@novell.com> L: platform-driver-x86@vger.kernel.org -W: https://tango.0pointer.de/mailman/listinfo/s270-linux -W: http://0pointer.de/lennart/tchibo.html S: Maintained F: drivers/platform/x86/msi-laptop.c @@ -3916,8 +3965,10 @@ S: Supported F: drivers/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM -S: Orphan +M: Chris Ball <cjb@laptop.org> L: linux-mmc@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git +S: Maintained F: drivers/mmc/ F: include/linux/mmc/ @@ -3939,7 +3990,7 @@ F: drivers/char/isicom.c F: include/linux/isicom.h MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER -M: Felipe Balbi <felipe.balbi@nokia.com> +M: Felipe Balbi <balbi@ti.com> L: linux-usb@vger.kernel.org T: git git://gitorious.org/usb/usb.git S: Maintained @@ -3959,8 +4010,8 @@ S: Maintained F: drivers/net/natsemi.c NCP FILESYSTEM -M: Petr Vandrovec <vandrove@vc.cvut.cz> -S: Maintained +M: Petr Vandrovec <petr@vandrovec.name> +S: Odd Fixes F: fs/ncpfs/ NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) @@ -4237,7 +4288,7 @@ S: Maintained F: drivers/char/hw_random/omap-rng.c OMAP USB SUPPORT -M: Felipe Balbi <felipe.balbi@nokia.com> +M: Felipe Balbi <balbi@ti.com> M: David Brownell <dbrownell@users.sourceforge.net> L: linux-usb@vger.kernel.org L: linux-omap@vger.kernel.org @@ -4991,6 +5042,12 @@ F: drivers/media/common/saa7146* F: drivers/media/video/*7146* F: include/media/*7146* +SAMSUNG AUDIO (ASoC) DRIVERS +M: Jassi Brar <jassi.brar@samsung.com> +L: alsa-devel@alsa-project.org (moderated for non-subscribers) +S: Supported +F: sound/soc/s3c24xx + TLG2300 VIDEO4LINUX-2 DRIVER M: Huang Shijie <shijie8@gmail.com> M: Kang Yong <kangyong@telegent.com> @@ -5088,8 +5145,10 @@ S: Maintained F: drivers/mmc/host/sdricoh_cs.c SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER -S: Orphan +M: Chris Ball <cjb@laptop.org> L: linux-mmc@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git +S: Maintained F: drivers/mmc/host/sdhci.* SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF) @@ -6431,8 +6490,10 @@ F: include/linux/wm97xx.h WOLFSON MICROELECTRONICS DRIVERS M: Mark Brown <broonie@opensource.wolfsonmicro.com> M: Ian Lartey <ian@opensource.wolfsonmicro.com> +M: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> +T: git git://opensource.wolfsonmicro.com/linux-2.6-asoc T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus -W: http://opensource.wolfsonmicro.com/node/8 +W: http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices S: Supported F: Documentation/hwmon/wm83?? F: drivers/leds/leds-wm83*.c @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 36 -EXTRAVERSION = -rc4 -NAME = Sheep on Meth +EXTRAVERSION = -rc8 +NAME = Flesh-Eating Bats with Fangs # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/arch/Kconfig b/arch/Kconfig index 4877a8c..fe48fc7 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -32,8 +32,9 @@ config HAVE_OPROFILE config KPROBES bool "Kprobes" - depends on KALLSYMS && MODULES + depends on MODULES depends on HAVE_KPROBES + select KALLSYMS help Kprobes allows you to trap at almost any kernel address and execute a callback function. register_kprobe() establishes @@ -45,7 +46,6 @@ config OPTPROBES def_bool y depends on KPROBES && HAVE_OPTPROBES depends on !PREEMPT - select KALLSYMS_ALL config HAVE_EFFICIENT_UNALIGNED_ACCESS bool diff --git a/arch/alpha/include/asm/cacheflush.h b/arch/alpha/include/asm/cacheflush.h index 01d71e1..012f124 100644 --- a/arch/alpha/include/asm/cacheflush.h +++ b/arch/alpha/include/asm/cacheflush.h @@ -43,6 +43,8 @@ extern void smp_imb(void); /* ??? Ought to use this in arch/alpha/kernel/signal.c too. */ #ifndef CONFIG_SMP +#include <linux/sched.h> + extern void __load_new_mm_context(struct mm_struct *); static inline void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index 804e531..058937b 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -449,10 +449,13 @@ #define __NR_pwritev 491 #define __NR_rt_tgsigqueueinfo 492 #define __NR_perf_event_open 493 +#define __NR_fanotify_init 494 +#define __NR_fanotify_mark 495 +#define __NR_prlimit64 496 #ifdef __KERNEL__ -#define NR_SYSCALLS 494 +#define NR_SYSCALLS 497 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR @@ -463,6 +466,7 @@ #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_RT_SIGSUSPEND /* "Conditional" syscalls. What we want is diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index b45d913..6d159ce 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -73,8 +73,6 @@ ldq $20, HAE_REG($19); \ stq $21, HAE_CACHE($19); \ stq $21, 0($20); \ - ldq $0, 0($sp); \ - ldq $1, 8($sp); \ 99:; \ ldq $19, 72($sp); \ ldq $20, 80($sp); \ @@ -316,19 +314,24 @@ ret_from_sys_call: cmovne $26, 0, $19 /* $19 = 0 => non-restartable */ ldq $0, SP_OFF($sp) and $0, 8, $0 - beq $0, restore_all -ret_from_reschedule: + beq $0, ret_to_kernel +ret_to_user: /* Make sure need_resched and sigpending don't change between sampling and the rti. */ lda $16, 7 call_pal PAL_swpipl ldl $5, TI_FLAGS($8) and $5, _TIF_WORK_MASK, $2 - bne $5, work_pending + bne $2, work_pending restore_all: RESTORE_ALL call_pal PAL_rti +ret_to_kernel: + lda $16, 7 + call_pal PAL_swpipl + br restore_all + .align 3 $syscall_error: /* @@ -363,7 +366,7 @@ $ret_success: * $8: current. * $19: The old syscall number, or zero if this is not a return * from a syscall that errored and is possibly restartable. - * $20: Error indication. + * $20: The old a3 value */ .align 4 @@ -392,12 +395,18 @@ $work_resched: $work_notifysig: mov $sp, $16 - br $1, do_switch_stack + bsr $1, do_switch_stack mov $sp, $17 mov $5, $18 + mov $19, $9 /* save old syscall number */ + mov $20, $10 /* save old a3 */ + and $5, _TIF_SIGPENDING, $2 + cmovne $2, 0, $9 /* we don't want double syscall restarts */ jsr $26, do_notify_resume + mov $9, $19 + mov $10, $20 bsr $1, undo_switch_stack - br restore_all + br ret_to_user .end work_pending /* @@ -430,6 +439,7 @@ strace: beq $1, 1f ldq $27, 0($2) 1: jsr $26, ($27), sys_gettimeofday +ret_from_straced: ldgp $gp, 0($26) /* check return.. */ @@ -650,7 +660,7 @@ kernel_thread: /* We don't actually care for a3 success widgetry in the kernel. Not for positive errno values. */ stq $0, 0($sp) /* $0 */ - br restore_all + br ret_to_kernel .end kernel_thread /* @@ -757,11 +767,15 @@ sys_vfork: .ent sys_sigreturn sys_sigreturn: .prologue 0 + lda $9, ret_from_straced + cmpult $26, $9, $9 mov $sp, $17 lda $18, -SWITCH_STACK_SIZE($sp) lda $sp, -SWITCH_STACK_SIZE($sp) jsr $26, do_sigreturn - br $1, undo_switch_stack + bne $9, 1f + jsr $26, syscall_trace +1: br $1, undo_switch_stack br ret_from_sys_call .end sys_sigreturn @@ -770,47 +784,19 @@ sys_sigreturn: .ent sys_rt_sigreturn sys_rt_sigreturn: .prologue 0 + lda $9, ret_from_straced + cmpult $26, $9, $9 mov $sp, $17 lda $18, -SWITCH_STACK_SIZE($sp) lda $sp, -SWITCH_STACK_SIZE($sp) jsr $26, do_rt_sigreturn - br $1, undo_switch_stack + bne $9, 1f + jsr $26, syscall_trace +1: br $1, undo_switch_stack br ret_from_sys_call .end sys_rt_sigreturn .align 4 - .globl sys_sigsuspend - .ent sys_sigsuspend -sys_sigsuspend: - .prologue 0 - mov $sp, $17 - br $1, do_switch_stack - mov $sp, $18 - subq $sp, 16, $sp - stq $26, 0($sp) - jsr $26, do_sigsuspend - ldq $26, 0($sp) - lda $sp, SWITCH_STACK_SIZE+16($sp) - ret -.end sys_sigsuspend - - .align 4 - .globl sys_rt_sigsuspend - .ent sys_rt_sigsuspend -sys_rt_sigsuspend: - .prologue 0 - mov $sp, $18 - br $1, do_switch_stack - mov $sp, $19 - subq $sp, 16, $sp - stq $26, 0($sp) - jsr $26, do_rt_sigsuspend - ldq $26, 0($sp) - lda $sp, SWITCH_STACK_SIZE+16($sp) - ret -.end sys_rt_sigsuspend - - .align 4 .globl sys_sethae .ent sys_sethae sys_sethae: @@ -929,15 +915,6 @@ sys_execve: .end sys_execve .align 4 - .globl osf_sigprocmask - .ent osf_sigprocmask -osf_sigprocmask: - .prologue 0 - mov $sp, $18 - jmp $31, sys_osf_sigprocmask -.end osf_sigprocmask - - .align 4 .globl alpha_ni_syscall .ent alpha_ni_syscall alpha_ni_syscall: diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c index 8ca6345..253cf1a 100644 --- a/arch/alpha/kernel/err_ev6.c +++ b/arch/alpha/kernel/err_ev6.c @@ -90,11 +90,13 @@ static int ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn, u64 c_stat, u64 c_sts, int print) { - char *sourcename[] = { "UNKNOWN", "UNKNOWN", "UNKNOWN", - "MEMORY", "BCACHE", "DCACHE", - "BCACHE PROBE", "BCACHE PROBE" }; - char *streamname[] = { "D", "I" }; - char *bitsname[] = { "SINGLE", "DOUBLE" }; + static const char * const sourcename[] = { + "UNKNOWN", "UNKNOWN", "UNKNOWN", + "MEMORY", "BCACHE", "DCACHE", + "BCACHE PROBE", "BCACHE PROBE" + }; + static const char * const streamname[] = { "D", "I" }; + static const char * const bitsname[] = { "SINGLE", "DOUBLE" }; int status = MCHK_DISPOSITION_REPORT; int source = -1, stream = -1, bits = -1; diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 5c905aa..648ae88 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c @@ -589,22 +589,23 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt) static void marvel_print_pox_trans_sum(u64 trans_sum) { - char *pcix_cmd[] = { "Interrupt Acknowledge", - "Special Cycle", - "I/O Read", - "I/O Write", - "Reserved", - "Reserved / Device ID Message", - "Memory Read", - "Memory Write", - "Reserved / Alias to Memory Read Block", - "Reserved / Alias to Memory Write Block", - "Configuration Read", - "Configuration Write", - "Memory Read Multiple / Split Completion", - "Dual Address Cycle", - "Memory Read Line / Memory Read Block", - "Memory Write and Invalidate / Memory Write Block" + static const char * const pcix_cmd[] = { + "Interrupt Acknowledge", + "Special Cycle", + "I/O Read", + "I/O Write", + "Reserved", + "Reserved / Device ID Message", + "Memory Read", + "Memory Write", + "Reserved / Alias to Memory Read Block", + "Reserved / Alias to Memory Write Block", + "Configuration Read", + "Configuration Write", + "Memory Read Multiple / Split Completion", + "Dual Address Cycle", + "Memory Read Line / Memory Read Block", + "Memory Write and Invalidate / Memory Write Block" }; #define IO7__POX_TRANSUM__PCI_ADDR__S (0) diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c index f7ed97c..c3b3781 100644 --- a/arch/alpha/kernel/err_titan.c +++ b/arch/alpha/kernel/err_titan.c @@ -75,8 +75,12 @@ titan_parse_p_serror(int which, u64 serror, int print) int status = MCHK_DISPOSITION_REPORT; #ifdef CONFIG_VERBOSE_MCHECK - char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"}; - char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"}; + static const char * const serror_src[] = { + "GPCI", "APCI", "AGP HP", "AGP LP" + }; + static const char * const serror_cmd[] = { + "DMA Read", "DMA RMW", "SGTE Read", "Reserved" + }; #endif /* CONFIG_VERBOSE_MCHECK */ #define TITAN__PCHIP_SERROR__LOST_UECC (1UL << 0) @@ -140,14 +144,15 @@ titan_parse_p_perror(int which, int port, u64 perror, int print) int status = MCHK_DISPOSITION_REPORT; #ifdef CONFIG_VERBOSE_MCHECK - char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle", - "I/O Read", "I/O Write", - "Reserved", "Reserved", - "Memory Read", "Memory Write", - "Reserved", "Reserved", - "Configuration Read", "Configuration Write", - "Memory Read Multiple", "Dual Address Cycle", - "Memory Read Line","Memory Write and Invalidate" + static const char * const perror_cmd[] = { + "Interrupt Acknowledge", "Special Cycle", + "I/O Read", "I/O Write", + "Reserved", "Reserved", + "Memory Read", "Memory Write", + "Reserved", "Reserved", + "Configuration Read", "Configuration Write", + "Memory Read Multiple", "Dual Address Cycle", + "Memory Read Line", "Memory Write and Invalidate" }; #endif /* CONFIG_VERBOSE_MCHECK */ @@ -273,11 +278,11 @@ titan_parse_p_agperror(int which, u64 agperror, int print) int cmd, len; unsigned long addr; - char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)", - "Write (low-priority)", - "Write (high-priority)", - "Reserved", "Reserved", - "Flush", "Fence" + static const char * const agperror_cmd[] = { + "Read (low-priority)", "Read (high-priority)", + "Write (low-priority)", "Write (high-priority)", + "Reserved", "Reserved", + "Flush", "Fence" }; #endif /* CONFIG_VERBOSE_MCHECK */ diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 5d1e6d6..547e8b8 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/stddef.h> #include <linux/syscalls.h> #include <linux/unistd.h> @@ -69,7 +68,6 @@ SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start, { struct mm_struct *mm; - lock_kernel(); mm = current->mm; mm->end_code = bss_start + bss_len; mm->start_brk = bss_start + bss_len; @@ -78,7 +76,6 @@ SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start, printk("set_program_attributes(%lx %lx %lx %lx)\n", text_start, text_len, bss_start, bss_len); #endif - unlock_kernel(); return 0; } @@ -517,7 +514,6 @@ SYSCALL_DEFINE2(osf_proplist_syscall, enum pl_code, code, long error; int __user *min_buf_size_ptr; - lock_kernel(); switch (code) { case PL_SET: if (get_user(error, &args->set.nbytes)) @@ -547,7 +543,6 @@ SYSCALL_DEFINE2(osf_proplist_syscall, enum pl_code, code, error = -EOPNOTSUPP; break; }; - unlock_kernel(); return error; } @@ -594,7 +589,7 @@ SYSCALL_DEFINE2(osf_sigstack, struct sigstack __user *, uss, SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) { - char *sysinfo_table[] = { + const char *sysinfo_table[] = { utsname()->sysname, utsname()->nodename, utsname()->release, @@ -606,7 +601,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) "dummy", /* secure RPC domain */ }; unsigned long offset; - char *res; + const char *res; long len, err = -EINVAL; offset = command-1; diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index 738fc82..b899e95 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -66,7 +66,7 @@ static int pci_mmap_resource(struct kobject *kobj, { struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); - struct resource *res = (struct resource *)attr->private; + struct resource *res = attr->private; enum pci_mmap_state mmap_type; struct pci_bus_region bar; int i; diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 842dba3..3ec3506 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -356,7 +356,7 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti) dest[27] = pt->r27; dest[28] = pt->r28; dest[29] = pt->gp; - dest[30] = rdusp(); + dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp; dest[31] = pt->pc; /* Once upon a time this was the PS value. Which is stupid diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 0932dbb..6f7feb5 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -41,46 +41,20 @@ static void do_signal(struct pt_regs *, struct switch_stack *, /* * The OSF/1 sigprocmask calling sequence is different from the * C sigprocmask() sequence.. - * - * how: - * 1 - SIG_BLOCK - * 2 - SIG_UNBLOCK - * 3 - SIG_SETMASK - * - * We change the range to -1 .. 1 in order to let gcc easily - * use the conditional move instructions. - * - * Note that we don't need to acquire the kernel lock for SMP - * operation, as all of this is local to this thread. */ -SYSCALL_DEFINE3(osf_sigprocmask, int, how, unsigned long, newmask, - struct pt_regs *, regs) +SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask) { - unsigned long oldmask = -EINVAL; - - if ((unsigned long)how-1 <= 2) { - long sign = how-2; /* -1 .. 1 */ - unsigned long block, unblock; - - newmask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - oldmask = current->blocked.sig[0]; - - unblock = oldmask & ~newmask; - block = oldmask | newmask; - if (!sign) - block = unblock; - if (sign <= 0) - newmask = block; - if (_NSIG_WORDS > 1 && sign > 0) - sigemptyset(¤t->blocked); - current->blocked.sig[0] = newmask; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->r0 = 0; /* special no error return */ + sigset_t oldmask; + sigset_t mask; + unsigned long res; + + siginitset(&mask, newmask & _BLOCKABLE); + res = sigprocmask(how, &mask, &oldmask); + if (!res) { + force_successful_syscall_return(); + res = oldmask.sig[0]; } - return oldmask; + return res; } SYSCALL_DEFINE3(osf_sigaction, int, sig, @@ -94,9 +68,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig, old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); new_ka.ka_restorer = NULL; } @@ -106,9 +80,9 @@ SYSCALL_DEFINE3(osf_sigaction, int, sig, if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; @@ -144,8 +118,7 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, /* * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage int -do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) +SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); @@ -154,41 +127,6 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - /* Indicate EINTR on return from any possible signal handler, - which will not come back through here, but via sigreturn. */ - regs->r0 = EINTR; - regs->r19 = 1; - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - -asmlinkage int -do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, - struct pt_regs *regs, struct switch_stack *sw) -{ - sigset_t set; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - if (copy_from_user(&set, uset, sizeof(set))) - return -EFAULT; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - /* Indicate EINTR on return from any possible signal handler, - which will not come back through here, but via sigreturn. */ - regs->r0 = EINTR; - regs->r19 = 1; - current->state = TASK_INTERRUPTIBLE; schedule(); set_thread_flag(TIF_RESTORE_SIGMASK); @@ -239,6 +177,8 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long usp; long i, err = __get_user(regs->pc, &sc->sc_pc); + current_thread_info()->restart_block.fn = do_no_restart_syscall; + sw->r26 = (unsigned long) ret_from_sys_call; err |= __get_user(regs->r0, sc->sc_regs+0); @@ -591,7 +531,6 @@ syscall_restart(unsigned long r0, unsigned long r19, regs->pc -= 4; break; case ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = do_no_restart_syscall; regs->r0 = EINTR; break; } diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c index 4afc1a1..f0df3fb 100644 --- a/arch/alpha/kernel/srm_env.c +++ b/arch/alpha/kernel/srm_env.c @@ -87,7 +87,7 @@ static int srm_env_proc_show(struct seq_file *m, void *v) srm_env_t *entry; char *page; - entry = (srm_env_t *)m->private; + entry = m->private; page = (char *)__get_free_page(GFP_USER); if (!page) return -ENOMEM; diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 09acb78..a6a1de9 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -58,7 +58,7 @@ sys_call_table: .quad sys_open /* 45 */ .quad alpha_ni_syscall .quad sys_getxgid - .quad osf_sigprocmask + .quad sys_osf_sigprocmask .quad alpha_ni_syscall .quad alpha_ni_syscall /* 50 */ .quad sys_acct @@ -512,6 +512,9 @@ sys_call_table: .quad sys_pwritev .quad sys_rt_tgsigqueueinfo .quad sys_perf_event_open + .quad sys_fanotify_init + .quad sys_fanotify_mark /* 495 */ + .quad sys_prlimit64 .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index eacceb2..396af17 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -191,16 +191,16 @@ irqreturn_t timer_interrupt(int irq, void *dev) write_sequnlock(&xtime_lock); -#ifndef CONFIG_SMP - while (nticks--) - update_process_times(user_mode(get_irq_regs())); -#endif - if (test_perf_event_pending()) { clear_perf_event_pending(); perf_event_do_pending(); } +#ifndef CONFIG_SMP + while (nticks--) + update_process_times(user_mode(get_irq_regs())); +#endif + return IRQ_HANDLED; } diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index b14f015..0414e02 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -13,7 +13,6 @@ #include <linux/sched.h> #include <linux/tty.h> #include <linux/delay.h> -#include <linux/smp_lock.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kallsyms.h> @@ -623,7 +622,6 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, return; } - lock_kernel(); printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n", pc, va, opcode, reg); do_exit(SIGSEGV); @@ -646,7 +644,6 @@ got_exception: * Yikes! No one to forward the exception to. * Since the registers are in a weird format, dump them ourselves. */ - lock_kernel(); printk("%s(%d): unhandled unaligned exception\n", current->comm, task_pid_nr(current)); diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 553b7cf..b27f8ab 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -271,7 +271,6 @@ config ARCH_AT91 bool "Atmel AT91" select ARCH_REQUIRE_GPIOLIB select HAVE_CLK - select ARCH_USES_GETTIMEOFFSET help This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 and AT91CAP9 processors. @@ -511,6 +510,7 @@ config ARCH_MMP select GENERIC_CLOCKEVENTS select TICK_ONESHOT select PLAT_PXA + select SPARSE_IRQ help Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line. @@ -588,6 +588,7 @@ config ARCH_PXA select GENERIC_CLOCKEVENTS select TICK_ONESHOT select PLAT_PXA + select SPARSE_IRQ help Support for Intel/Marvell's PXA2xx/PXA3xx processor line. @@ -679,8 +680,8 @@ config ARCH_S3C64XX help Samsung S3C64XX series based systems -config ARCH_S5P6440 - bool "Samsung S5P6440" +config ARCH_S5P64X0 + bool "Samsung S5P6440 S5P6450" select CPU_V6 select GENERIC_GPIO select HAVE_CLK @@ -689,7 +690,8 @@ config ARCH_S5P6440 select HAVE_S3C2410_I2C select HAVE_S3C_RTC help - Samsung S5P6440 CPU based systems + Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440, + SMDK6450. config ARCH_S5P6442 bool "Samsung S5P6442" @@ -748,6 +750,15 @@ config ARCH_SHARK Support for the StrongARM based Digital DNARD machine, also known as "Shark" (<http://www.shark-linux.de/shark.html>). +config ARCH_TCC_926 + bool "Telechips TCC ARM926-based systems" + select CPU_ARM926T + select HAVE_CLK + select COMMON_CLKDEV + select GENERIC_CLOCKEVENTS + help + Support for Telechips TCC ARM926-based systems. + config ARCH_LH7A40X bool "Sharp LH7A40X" select CPU_ARM922T @@ -916,6 +927,8 @@ source "arch/arm/plat-s5p/Kconfig" source "arch/arm/plat-spear/Kconfig" +source "arch/arm/plat-tcc/Kconfig" + if ARCH_S3C2410 source "arch/arm/mach-s3c2400/Kconfig" source "arch/arm/mach-s3c2410/Kconfig" @@ -929,7 +942,7 @@ if ARCH_S3C64XX source "arch/arm/mach-s3c64xx/Kconfig" endif -source "arch/arm/mach-s5p6440/Kconfig" +source "arch/arm/mach-s5p64x0/Kconfig" source "arch/arm/mach-s5p6442/Kconfig" @@ -1051,6 +1064,32 @@ config ARM_ERRATA_460075 ACTLR register. Note that setting specific bits in the ACTLR register may not be available in non-secure mode. +config ARM_ERRATA_742230 + bool "ARM errata: DMB operation may be faulty" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 742230 Cortex-A9 + (r1p0..r2p2) erratum. Under rare circumstances, a DMB instruction + between two write operations may not ensure the correct visibility + ordering of the two writes. This workaround sets a specific bit in + the diagnostic register of the Cortex-A9 which causes the DMB + instruction to behave as a DSB, ensuring the correct behaviour of + the two writes. + +config ARM_ERRATA_742231 + bool "ARM errata: Incorrect hazard handling in the SCU may lead to data corruption" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 742231 Cortex-A9 + (r2p0..r2p2) erratum. Under certain conditions, specific to the + Cortex-A9 MPCore micro-architecture, two CPUs working in SMP mode, + accessing some data located in the same cache line, may get corrupted + data due to bad handling of the address hazard when the line gets + replaced from one of the CPUs at the same time as another CPU is + accessing it. This workaround sets specific bits in the diagnostic + register of the Cortex-A9 which reduces the linefill issuing + capabilities of the processor. + config PL310_ERRATA_588369 bool "Clean & Invalidate maintenance operations do not invalidate clean lines" depends on CACHE_L2X0 && ARCH_OMAP4 @@ -1076,6 +1115,20 @@ config ARM_ERRATA_720789 invalidated are not, resulting in an incoherency in the system page tables. The workaround changes the TLB flushing routines to invalidate entries regardless of the ASID. + +config ARM_ERRATA_743622 + bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption" + depends on CPU_V7 + help + This option enables the workaround for the 743622 Cortex-A9 + (r2p0..r2p2) erratum. Under very rare conditions, a faulty + optimisation in the Cortex-A9 Store Buffer may lead to data + corruption. This workaround sets a specific bit in the diagnostic + register of the Cortex-A9 which disables the Store Buffer + optimisation, preventing the defect from occurring. This has no + visible impact on the overall performance or power consumption of the + processor. + endmenu source "arch/arm/common/Kconfig" @@ -1232,7 +1285,7 @@ source kernel/Kconfig.preempt config HZ int - default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || \ + default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \ ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310 default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER default AT91_TIMER_HZ if ARCH_AT91 @@ -1438,6 +1491,20 @@ config UACCESS_WITH_MEMCPY However, if the CPU data cache is using a write-allocate mode, this option is unlikely to provide any performance gain. +config SECCOMP + bool + prompt "Enable seccomp to safely compute untrusted bytecode" + ---help--- + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via prctl(PR_SET_SECCOMP), it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + config CC_STACKPROTECTOR bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" help diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 91344af..c29fb38 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -2,6 +2,20 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config STRICT_DEVMEM + bool "Filter access to /dev/mem" + depends on MMU + ---help--- + If this option is disabled, you allow userspace (root) access to all + of memory, including kernel and userspace memory. Accidental + access to this is obviously disastrous, but specific access can + be used by people debugging the kernel. + + If this option is switched on, the /dev/mem file only allows + userspace access to memory mapped peripherals. + + If in doubt, say Y. + # RMK wants arm kernels compiled with frame pointers or stack unwinding. # If you know what you are doing and are willing to live without stack # traces, you can get a slightly smaller kernel by setting this option to diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 59c1ce8..b87aed0 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -173,7 +173,7 @@ machine-$(CONFIG_ARCH_RPC) := rpc machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443 machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx -machine-$(CONFIG_ARCH_S5P6440) := s5p6440 +machine-$(CONFIG_ARCH_S5P64X0) := s5p64x0 machine-$(CONFIG_ARCH_S5P6442) := s5p6442 machine-$(CONFIG_ARCH_S5PC100) := s5pc100 machine-$(CONFIG_ARCH_S5PV210) := s5pv210 @@ -183,6 +183,7 @@ machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_SHMOBILE) := shmobile machine-$(CONFIG_ARCH_STMP378X) := stmp378x machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx +machine-$(CONFIG_ARCH_TCC8K) := tcc8k machine-$(CONFIG_ARCH_TEGRA) := tegra machine-$(CONFIG_ARCH_U300) := u300 machine-$(CONFIG_ARCH_U8500) := ux500 @@ -202,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC) := mxc plat-$(CONFIG_ARCH_OMAP) := omap plat-$(CONFIG_ARCH_S3C64XX) := samsung plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx +plat-$(CONFIG_ARCH_TCC_926) := tcc plat-$(CONFIG_PLAT_IOP) := iop plat-$(CONFIG_PLAT_NOMADIK) := nomadik plat-$(CONFIG_PLAT_ORION) := orion @@ -245,13 +247,14 @@ ifeq ($(FASTFPE),$(wildcard $(FASTFPE))) FASTFPE_OBJ :=$(FASTFPE)/ endif -# If we have a machine-specific directory, then include it in the build. -core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ -core-y += $(machdirs) $(platdirs) core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) core-$(CONFIG_VFP) += arch/arm/vfp/ +# If we have a machine-specific directory, then include it in the build. +core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ +core-y += $(machdirs) $(platdirs) + drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ libs-y := arch/arm/lib/ $(libs-y) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index b23f6bc..65a7c1c 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -116,5 +116,5 @@ CFLAGS_font.o := -Dstatic= $(obj)/font.c: $(FONTC) $(call cmd,shipped) -$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config +$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG) @sed "$(SEDFLAGS)" < $< > $@ diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 7dfa9a8..ada6359 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -67,25 +67,11 @@ static inline unsigned int gic_irq(unsigned int irq) /* * Routines to acknowledge, disable and enable interrupts - * - * Linux assumes that when we're done with an interrupt we need to - * unmask it, in the same way we need to unmask an interrupt when - * we first enable it. - * - * The GIC has a separate notion of "end of interrupt" to re-enable - * an interrupt after handling, in order to support hardware - * prioritisation. - * - * We can make the GIC behave in the way that Linux expects by making - * our "acknowledge" routine disable the interrupt, then mark it as - * complete. */ static void gic_ack_irq(unsigned int irq) { - u32 mask = 1 << (irq % 32); spin_lock(&irq_controller_lock); - writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4); writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI); spin_unlock(&irq_controller_lock); } diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 7974baa..1bec96e 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c @@ -271,6 +271,14 @@ int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); } +int dma_set_coherent_mask(struct device *dev, u64 mask) +{ + if (mask >= PHYS_OFFSET + SZ_64M - 1) + return 0; + + return -EIO; +} + int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) { it8152_io.start = IT8152_IO_BASE + 0x12000; diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig index f1bac70..9e90e6d 100644 --- a/arch/arm/configs/at91sam9g20ek_defconfig +++ b/arch/arm/configs/at91sam9g20ek_defconfig @@ -13,6 +13,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91SAM9G20=y CONFIG_MACH_AT91SAM9G20EK=y +CONFIG_MACH_AT91SAM9G20EK_2MMC=y CONFIG_AT91_PROGRAMMABLE_CLOCKS=y # CONFIG_ARM_THUMB is not set CONFIG_AEABI=y diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig index ccc9c99..2f70428 100644 --- a/arch/arm/configs/kirkwood_defconfig +++ b/arch/arm/configs/kirkwood_defconfig @@ -15,6 +15,7 @@ CONFIG_MACH_MV88F6281GTW_GE=y CONFIG_MACH_SHEEVAPLUG=y CONFIG_MACH_ESATA_SHEEVAPLUG=y CONFIG_MACH_GURUPLUG=y +CONFIG_MACH_DOCKSTAR=y CONFIG_MACH_TS219=y CONFIG_MACH_TS41X=y CONFIG_MACH_OPENRD_BASE=y diff --git a/arch/arm/configs/s5p6440_defconfig b/arch/arm/configs/s5p64x0_defconfig index 0b0266c..2993ecd 100644 --- a/arch/arm/configs/s5p6440_defconfig +++ b/arch/arm/configs/s5p64x0_defconfig @@ -5,10 +5,11 @@ CONFIG_KALLSYMS_ALL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_ARCH_S5P6440=y +CONFIG_ARCH_S5P64X0=y CONFIG_S3C_BOOT_ERROR_RESET=y CONFIG_S3C_LOWLEVEL_UART_PORT=1 CONFIG_MACH_SMDK6440=y +CONFIG_MACH_SMDK6450=y CONFIG_CPU_32v6K=y CONFIG_AEABI=y CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc" diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index 5747a8b..8bb66bc 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -127,4 +127,8 @@ struct mm_struct; extern unsigned long arch_randomize_brk(struct mm_struct *mm); #define arch_randomize_brk arch_randomize_brk +extern int vectors_user_mapping(void); +#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping() +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES + #endif diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 1261b1f9..815efa2 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -294,6 +294,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr); #define ARCH_HAS_VALID_PHYS_ADDR_RANGE extern int valid_phys_addr_range(unsigned long addr, size_t size); extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); +extern int devmem_is_allowed(unsigned long pfn); #endif /* diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h index a0b3cac..71605d9 100644 --- a/arch/arm/include/asm/mmu_context.h +++ b/arch/arm/include/asm/mmu_context.h @@ -18,7 +18,6 @@ #include <asm/cacheflush.h> #include <asm/cachetype.h> #include <asm/proc-fns.h> -#include <asm-generic/mm_hooks.h> void __check_kvm_seq(struct mm_struct *mm); @@ -134,4 +133,32 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, #define deactivate_mm(tsk,mm) do { } while (0) #define activate_mm(prev,next) switch_mm(prev, next, NULL) +/* + * We are inserting a "fake" vma for the user-accessible vector page so + * gdb and friends can get to it through ptrace and /proc/<pid>/mem. + * But we also want to remove it before the generic code gets to see it + * during process exit or the unmapping of it would cause total havoc. + * (the macro is used as remove_vma() is static to mm/mmap.c) + */ +#define arch_exit_mmap(mm) \ +do { \ + struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \ + if (high_vma) { \ + BUG_ON(high_vma->vm_next); /* it should be last */ \ + if (high_vma->vm_prev) \ + high_vma->vm_prev->vm_next = NULL; \ + else \ + mm->mmap = NULL; \ + rb_erase(&high_vma->vm_rb, &mm->mm_rb); \ + mm->mmap_cache = NULL; \ + mm->map_count--; \ + remove_vma(high_vma); \ + } \ +} while (0) + +static inline void arch_dup_mmap(struct mm_struct *oldmm, + struct mm_struct *mm) +{ +} + #endif diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index ab68cf1..e90b167 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -317,6 +317,10 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; } #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE #define pgprot_dmacoherent(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE) +#define __HAVE_PHYS_MEM_ACCESS_PROT +struct file; +extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); #else #define pgprot_dmacoherent(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED) diff --git a/arch/arm/include/asm/seccomp.h b/arch/arm/include/asm/seccomp.h new file mode 100644 index 0000000..52b156b --- /dev/null +++ b/arch/arm/include/asm/seccomp.h @@ -0,0 +1,11 @@ +#ifndef _ASM_ARM_SECCOMP_H +#define _ASM_ARM_SECCOMP_H + +#include <linux/unistd.h> + +#define __NR_seccomp_read __NR_read +#define __NR_seccomp_write __NR_write +#define __NR_seccomp_exit __NR_exit +#define __NR_seccomp_sigreturn __NR_rt_sigreturn + +#endif /* _ASM_ARM_SECCOMP_H */ diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 763e29f..7b5cc8d 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -144,6 +144,7 @@ extern void vfp_flush_hwstate(struct thread_info *); #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_FREEZE 19 #define TIF_RESTORE_SIGMASK 20 +#define TIF_SECCOMP 21 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) @@ -153,6 +154,7 @@ extern void vfp_flush_hwstate(struct thread_info *); #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) #define _TIF_FREEZE (1 << TIF_FREEZE) #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) +#define _TIF_SECCOMP (1 << TIF_SECCOMP) /* * Change these and you break ASM code in entry-common.S diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f05a35a..0385a82 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -48,6 +48,8 @@ work_pending: beq no_work_pending mov r0, sp @ 'regs' mov r2, why @ 'syscall' + tst r1, #_TIF_SIGPENDING @ delivering a signal? + movne why, #0 @ prevent further restarts bl do_notify_resume b ret_slow_syscall @ Check work again @@ -293,7 +295,6 @@ ENTRY(vector_swi) get_thread_info tsk adr tbl, sys_call_table @ load syscall table pointer - ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing #if defined(CONFIG_OABI_COMPAT) /* @@ -310,8 +311,20 @@ ENTRY(vector_swi) eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif + ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing stmdb sp!, {r4, r5} @ push fifth and sixth args - tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? + +#ifdef CONFIG_SECCOMP + tst r10, #_TIF_SECCOMP + beq 1f + mov r0, scno + bl __secure_computing + add r0, sp, #S_R0 + S_OFF @ pointer to regs + ldmia r0, {r0 - r3} @ have to reload r0 - r3 +1: +#endif + + tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? bne __sys_trace cmp scno, #NR_syscalls @ check upper syscall limit @@ -418,11 +431,13 @@ ENDPROC(sys_clone_wrapper) sys_sigreturn_wrapper: add r0, sp, #S_OFF + mov why, #0 @ prevent syscall restart handling b sys_sigreturn ENDPROC(sys_sigreturn_wrapper) sys_rt_sigreturn_wrapper: add r0, sp, #S_OFF + mov why, #0 @ prevent syscall restart handling b sys_rt_sigreturn ENDPROC(sys_rt_sigreturn_wrapper) diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c index 8bccbfa..2c1f005 100644 --- a/arch/arm/kernel/kprobes-decode.c +++ b/arch/arm/kernel/kprobes-decode.c @@ -1162,11 +1162,12 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi) { /* * MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx - * Undef : cccc 0011 0x00 xxxx xxxx xxxx xxxx xxxx + * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx * ALU op with S bit and Rd == 15 : * cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ - if ((insn & 0x0f900000) == 0x03200000 || /* MSR & Undef */ + if ((insn & 0x0fb00000) == 0x03200000 || /* MSR */ + (insn & 0x0ff00000) == 0x03400000 || /* Undef */ (insn & 0x0e10f000) == 0x0210f000) /* ALU s-bit, R15 */ return INSN_REJECTED; @@ -1177,7 +1178,7 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi) * *S (bit 20) updates condition codes * ADC/SBC/RSC reads the C flag */ - insn &= 0xfff00fff; /* Rn = r0, Rd = r0 */ + insn &= 0xffff0fff; /* Rd = r0 */ asi->insn[0] = insn; asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */ emulate_alu_imm_rwflags : emulate_alu_imm_rflags; diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 401e38b..66ac9c9 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -458,3 +458,24 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) unsigned long range_end = mm->brk + 0x02000000; return randomize_range(mm->brk, range_end, 0) ? : mm->brk; } + +/* + * The vectors page is always readable from user space for the + * atomic helpers and the signal restart code. Let's declare a mapping + * for it so it is visible through ptrace and /proc/<pid>/mem. + */ + +int vectors_user_mapping(void) +{ + struct mm_struct *mm = current->mm; + return install_special_mapping(mm, 0xffff0000, PAGE_SIZE, + VM_READ | VM_EXEC | + VM_MAYREAD | VM_MAYEXEC | + VM_ALWAYSDUMP | VM_RESERVED, + NULL); +} + +const char *arch_vma_name(struct vm_area_struct *vma) +{ + return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL; +} diff --git a/arch/arm/mach-aaec2000/include/mach/vmalloc.h b/arch/arm/mach-aaec2000/include/mach/vmalloc.h index 551f68f..cff4e0a 100644 --- a/arch/arm/mach-aaec2000/include/mach/vmalloc.h +++ b/arch/arm/mach-aaec2000/include/mach/vmalloc.h @@ -11,6 +11,6 @@ #ifndef __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 #endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 939bccd..bbd5efa 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -33,6 +33,7 @@ config ARCH_AT91SAM9260 select HAVE_AT91_USART3 select HAVE_AT91_USART4 select HAVE_AT91_USART5 + select HAVE_NET_MACB config ARCH_AT91SAM9261 bool "AT91SAM9261" @@ -51,6 +52,7 @@ config ARCH_AT91SAM9263 select CPU_ARM926T select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL + select HAVE_NET_MACB config ARCH_AT91SAM9RL bool "AT91SAM9RL" @@ -66,6 +68,7 @@ config ARCH_AT91SAM9G20 select HAVE_AT91_USART3 select HAVE_AT91_USART4 select HAVE_AT91_USART5 + select HAVE_NET_MACB config ARCH_AT91SAM9G45 bool "AT91SAM9G45" @@ -73,6 +76,7 @@ config ARCH_AT91SAM9G45 select GENERIC_CLOCKEVENTS select HAVE_AT91_USART3 select HAVE_FB_ATMEL + select HAVE_NET_MACB config ARCH_AT91CAP9 bool "AT91CAP9" @@ -338,6 +342,7 @@ config MACH_AT91SAM9G20EK that embeds only one SD/MMC slot. config MACH_AT91SAM9G20EK_2MMC + depends on MACH_AT91SAM9G20EK bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots" select HAVE_NAND_ATMEL_BUSWIDTH_16 help @@ -383,8 +388,8 @@ if ARCH_AT91SAM9G45 comment "AT91SAM9G45 Board Type" -config MACH_AT91SAM9G45EKES - bool "Atmel AT91SAM9G45-EKES Evaluation Kit" +config MACH_AT91SAM9M10G45EK + bool "Atmel AT91SAM9M10G45-EK Evaluation Kits" select HAVE_NAND_ATMEL_BUSWIDTH_16 help Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit. diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index ca2ac00..3a07a36 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -61,7 +61,6 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o # AT91SAM9G20 board-specific support obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o -obj-$(CONFIG_MACH_AT91SAM9G20EK_2MMC) += board-sam9g20ek-2slot-mmc.o obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o @@ -70,7 +69,7 @@ obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o # AT91SAM9G45 board-specific support -obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o +obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o # AT91CAP9 board-specific support obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 5e71ccd..1276bab 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -426,7 +426,7 @@ static struct i2c_gpio_platform_data pdata_i2c0 = { .sda_is_open_drain = 1, .scl_pin = AT91_PIN_PA21, .scl_is_open_drain = 1, - .udelay = 2, /* ~100 kHz */ + .udelay = 5, /* ~100 kHz */ }; static struct platform_device at91sam9g45_twi0_device = { @@ -440,7 +440,7 @@ static struct i2c_gpio_platform_data pdata_i2c1 = { .sda_is_open_drain = 1, .scl_pin = AT91_PIN_PB11, .scl_is_open_drain = 1, - .udelay = 2, /* ~100 kHz */ + .udelay = 5, /* ~100 kHz */ }; static struct platform_device at91sam9g45_twi1_device = { diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c index 5daff27..4665162 100644 --- a/arch/arm/mach-at91/board-at572d940hf_ek.c +++ b/arch/arm/mach-at91/board-at572d940hf_ek.c @@ -216,7 +216,7 @@ static struct atmel_nand_data __initdata eb_nand_data = { /* .rdy_pin = AT91_PIN_PC16, */ .enable_pin = AT91_PIN_PA15, .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) +#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) .bus_width_16 = 1, #else .bus_width_16 = 0, diff --git a/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c b/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c deleted file mode 100644 index c49f5c0..0000000 --- a/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2005 SAN People - * Copyright (C) 2008 Atmel - * Copyright (C) 2009 Rob Emanuele - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/types.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/spi/spi.h> -#include <linux/spi/at73c213.h> -#include <linux/clk.h> -#include <linux/regulator/machine.h> -#include <linux/regulator/fixed.h> -#include <linux/regulator/consumer.h> - -#include <mach/hardware.h> -#include <asm/setup.h> -#include <asm/mach-types.h> -#include <asm/irq.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> - -#include <mach/board.h> -#include <mach/gpio.h> -#include <mach/at91sam9_smc.h> - -#include "sam9_smc.h" -#include "generic.h" - - -static void __init ek_map_io(void) -{ - /* Initialize processor: 18.432 MHz crystal */ - at91sam9260_initialize(18432000); - - /* DGBU on ttyS0. (Rx & Tx only) */ - at91_register_uart(0, 0, 0); - - /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ - at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS - | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD - | ATMEL_UART_RI); - - /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */ - at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS); - - /* set serial console to ttyS0 (ie, DBGU) */ - at91_set_serial_console(0); -} - -static void __init ek_init_irq(void) -{ - at91sam9260_init_interrupts(NULL); -} - - -/* - * USB Host port - */ -static struct at91_usbh_data __initdata ek_usbh_data = { - .ports = 2, -}; - -/* - * USB Device port - */ -static struct at91_udc_data __initdata ek_udc_data = { - .vbus_pin = AT91_PIN_PC5, - .pullup_pin = 0, /* pull-up driven by UDC */ -}; - - -/* - * SPI devices. - */ -static struct spi_board_info ek_spi_devices[] = { -#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91)) - { /* DataFlash chip */ - .modalias = "mtd_dataflash", - .chip_select = 1, - .max_speed_hz = 15 * 1000 * 1000, - .bus_num = 0, - }, -#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) - { /* DataFlash card */ - .modalias = "mtd_dataflash", - .chip_select = 0, - .max_speed_hz = 15 * 1000 * 1000, - .bus_num = 0, - }, -#endif -#endif -}; - - -/* - * MACB Ethernet device - */ -static struct at91_eth_data __initdata ek_macb_data = { - .phy_irq_pin = AT91_PIN_PB0, - .is_rmii = 1, -}; - - -/* - * NAND flash - */ -static struct mtd_partition __initdata ek_nand_partition[] = { - { - .name = "Bootstrap", - .offset = 0, - .size = 4 * SZ_1M, - }, - { - .name = "Partition 1", - .offset = MTDPART_OFS_NXTBLK, - .size = 60 * SZ_1M, - }, - { - .name = "Partition 2", - .offset = MTDPART_OFS_NXTBLK, - .size = MTDPART_SIZ_FULL, - }, -}; - -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) -{ - *num_partitions = ARRAY_SIZE(ek_nand_partition); - return ek_nand_partition; -} - -/* det_pin is not connected */ -static struct atmel_nand_data __initdata ek_nand_data = { - .ale = 21, - .cle = 22, - .rdy_pin = AT91_PIN_PC13, - .enable_pin = AT91_PIN_PC14, - .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) - .bus_width_16 = 1, -#else - .bus_width_16 = 0, -#endif -}; - -static struct sam9_smc_config __initdata ek_nand_smc_config = { - .ncs_read_setup = 0, - .nrd_setup = 2, - .ncs_write_setup = 0, - .nwe_setup = 2, - - .ncs_read_pulse = 4, - .nrd_pulse = 4, - .ncs_write_pulse = 4, - .nwe_pulse = 4, - - .read_cycle = 7, - .write_cycle = 7, - - .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, - .tdf_cycles = 3, -}; - -static void __init ek_add_device_nand(void) -{ - /* setup bus-width (8 or 16) */ - if (ek_nand_data.bus_width_16) - ek_nand_smc_config.mode |= AT91_SMC_DBW_16; - else - ek_nand_smc_config.mode |= AT91_SMC_DBW_8; - - /* configure chip-select 3 (NAND) */ - sam9_smc_configure(3, &ek_nand_smc_config); - - at91_add_device_nand(&ek_nand_data); -} - - -/* - * MCI (SD/MMC) - * wp_pin is not connected - */ -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -static struct mci_platform_data __initdata ek_mmc_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = AT91_PIN_PC2, - .wp_pin = -ENODEV, - }, - .slot[1] = { - .bus_width = 4, - .detect_pin = AT91_PIN_PC9, - .wp_pin = -ENODEV, - }, - -}; -#else -static struct at91_mmc_data __initdata ek_mmc_data = { - .slot_b = 1, /* Only one slot so use slot B */ - .wire4 = 1, - .det_pin = AT91_PIN_PC9, -}; -#endif - -/* - * LEDs - */ -static struct gpio_led ek_leds[] = { - { /* "bottom" led, green, userled1 to be defined */ - .name = "ds5", - .gpio = AT91_PIN_PB8, - .active_low = 1, - .default_trigger = "none", - }, - { /* "power" led, yellow */ - .name = "ds1", - .gpio = AT91_PIN_PB9, - .default_trigger = "heartbeat", - } -}; - -#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE) -static struct regulator_consumer_supply ek_audio_consumer_supplies[] = { - REGULATOR_SUPPLY("AVDD", "0-001b"), - REGULATOR_SUPPLY("HPVDD", "0-001b"), - REGULATOR_SUPPLY("DBVDD", "0-001b"), - REGULATOR_SUPPLY("DCVDD", "0-001b"), -}; - -static struct regulator_init_data ek_avdd_reg_init_data = { - .constraints = { - .name = "3V3", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = ek_audio_consumer_supplies, - .num_consumer_supplies = ARRAY_SIZE(ek_audio_consumer_supplies), -}; - -static struct fixed_voltage_config ek_vdd_pdata = { - .supply_name = "board-3V3", - .microvolts = 3300000, - .gpio = -EINVAL, - .enabled_at_boot = 0, - .init_data = &ek_avdd_reg_init_data, -}; -static struct platform_device ek_voltage_regulator = { - .name = "reg-fixed-voltage", - .id = -1, - .num_resources = 0, - .dev = { - .platform_data = &ek_vdd_pdata, - }, -}; -static void __init ek_add_regulators(void) -{ - platform_device_register(&ek_voltage_regulator); -} -#else -static void __init ek_add_regulators(void) {} -#endif - -static struct i2c_board_info __initdata ek_i2c_devices[] = { - { - I2C_BOARD_INFO("24c512", 0x50), - }, -}; - - -static void __init ek_board_init(void) -{ - /* Serial */ - at91_add_device_serial(); - /* USB Host */ - at91_add_device_usbh(&ek_usbh_data); - /* USB Device */ - at91_add_device_udc(&ek_udc_data); - /* SPI */ - at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); - /* NAND */ - ek_add_device_nand(); - /* Ethernet */ - at91_add_device_eth(&ek_macb_data); - /* Regulators */ - ek_add_regulators(); - /* MMC */ -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) - at91_add_device_mci(0, &ek_mmc_data); -#else - at91_add_device_mmc(0, &ek_mmc_data); -#endif - /* I2C */ - at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); - /* LEDs */ - at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); - /* PCK0 provides MCLK to the WM8731 */ - at91_set_B_periph(AT91_PIN_PC1, 0); - /* SSC (for WM8731) */ - at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX); -} - -MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod") - /* Maintainer: Rob Emanuele */ - .phys_io = AT91_BASE_SYS, - .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, - .boot_params = AT91_SDRAM_BASE + 0x100, - .timer = &at91sam926x_timer, - .map_io = ek_map_io, - .init_irq = ek_init_irq, - .init_machine = ek_board_init, -MACHINE_END diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index 6ea9808..b463e34 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -47,6 +47,18 @@ #include "sam9_smc.h" #include "generic.h" +/* + * board revision encoding + * bit 0: + * 0 => 1 sd/mmc slot + * 1 => 2 sd/mmc slots connectors (board from revision C) + */ +#define HAVE_2MMC (1 << 0) +static int inline ek_have_2mmc(void) +{ + return machine_is_at91sam9g20ek_2mmc() || (system_rev & HAVE_2MMC); +} + static void __init ek_map_io(void) { @@ -94,7 +106,7 @@ static struct at91_udc_data __initdata ek_udc_data = { * SPI devices. */ static struct spi_board_info ek_spi_devices[] = { -#if !defined(CONFIG_MMC_AT91) +#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91)) { /* DataFlash chip */ .modalias = "mtd_dataflash", .chip_select = 1, @@ -121,6 +133,13 @@ static struct at91_eth_data __initdata ek_macb_data = { .is_rmii = 1, }; +static void __init ek_add_device_macb(void) +{ + if (ek_have_2mmc()) + ek_macb_data.phy_irq_pin = AT91_PIN_PB0; + + at91_add_device_eth(&ek_macb_data); +} /* * NAND flash @@ -198,13 +217,36 @@ static void __init ek_add_device_nand(void) /* * MCI (SD/MMC) - * det_pin, wp_pin and vcc_pin are not connected + * wp_pin and vcc_pin are not connected */ +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) +static struct mci_platform_data __initdata ek_mmc_data = { + .slot[1] = { + .bus_width = 4, + .detect_pin = AT91_PIN_PC9, + }, + +}; +#else static struct at91_mmc_data __initdata ek_mmc_data = { - .slot_b = 1, + .slot_b = 1, /* Only one slot so use slot B */ .wire4 = 1, + .det_pin = AT91_PIN_PC9, }; +#endif +static void __init ek_add_device_mmc(void) +{ +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) + if (ek_have_2mmc()) { + ek_mmc_data.slot[0].bus_width = 4; + ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2; + } + at91_add_device_mci(0, &ek_mmc_data); +#else + at91_add_device_mmc(0, &ek_mmc_data); +#endif +} /* * LEDs @@ -223,6 +265,15 @@ static struct gpio_led ek_leds[] = { } }; +static void __init ek_add_device_gpio_leds(void) +{ + if (ek_have_2mmc()) { + ek_leds[0].gpio = AT91_PIN_PB8; + ek_leds[1].gpio = AT91_PIN_PB9; + } + + at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); +} /* * GPIO Buttons @@ -336,15 +387,15 @@ static void __init ek_board_init(void) /* NAND */ ek_add_device_nand(); /* Ethernet */ - at91_add_device_eth(&ek_macb_data); + ek_add_device_macb(); /* Regulators */ ek_add_regulators(); /* MMC */ - at91_add_device_mmc(0, &ek_mmc_data); + ek_add_device_mmc(); /* I2C */ at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); /* LEDs */ - at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); + ek_add_device_gpio_leds(); /* Push Buttons */ ek_add_device_buttons(); /* PCK0 provides MCLK to the WM8731 */ @@ -363,3 +414,14 @@ MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK") .init_irq = ek_init_irq, .init_machine = ek_board_init, MACHINE_END + +MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index ee80059..ae0e084 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -135,7 +135,7 @@ static struct atmel_nand_data __initdata ek_nand_data = { .rdy_pin = AT91_PIN_PC8, .enable_pin = AT91_PIN_PC14, .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) +#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) .bus_width_16 = 1, #else .bus_width_16 = 0, @@ -399,7 +399,7 @@ static void __init ek_board_init(void) at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); } -MACHINE_START(AT91SAM9G45EKES, "Atmel AT91SAM9G45-EKES") +MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK") /* Maintainer: Atmel */ .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, diff --git a/arch/arm/mach-at91/include/mach/at91x40.h b/arch/arm/mach-at91/include/mach/at91x40.h index d34cdb8..063ac44 100644 --- a/arch/arm/mach-at91/include/mach/at91x40.h +++ b/arch/arm/mach-at91/include/mach/at91x40.h @@ -52,4 +52,10 @@ #define AT91_DBGU_CIDR (AT91_SF + 0) /* CIDR in PS segment */ #define AT91_DBGU_EXID (AT91_SF + 4) /* EXID in PS segment */ +/* + * Support defines for the simple Power Controller module. + */ +#define AT91_PS_CR (AT91_PS + 0) /* PS Control register */ +#define AT91_PS_CR_CPU (1 << 0) /* CPU clock disable bit */ + #endif /* AT91X40_H */ diff --git a/arch/arm/mach-at91/include/mach/system.h b/arch/arm/mach-at91/include/mach/system.h index c80e090..36af14b 100644 --- a/arch/arm/mach-at91/include/mach/system.h +++ b/arch/arm/mach-at91/include/mach/system.h @@ -28,17 +28,20 @@ static inline void arch_idle(void) { -#ifndef CONFIG_DEBUG_KERNEL /* * Disable the processor clock. The processor will be automatically * re-enabled by an interrupt or by a reset. */ - at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK); +#ifdef AT91_PS + at91_sys_write(AT91_PS_CR, AT91_PS_CR_CPU); #else + at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK); +#endif +#ifndef CONFIG_CPU_ARM920T /* * Set the processor (CP15) into 'Wait for Interrupt' mode. - * Unlike disabling the processor clock via the PMC (above) - * this allows the processor to be woken via JTAG. + * Post-RM9200 processors need this in conjunction with the above + * to save power when idle. */ cpu_do_idle(); #endif diff --git a/arch/arm/mach-bcmring/include/mach/vmalloc.h b/arch/arm/mach-bcmring/include/mach/vmalloc.h index 35e2ead..3db3a09 100644 --- a/arch/arm/mach-bcmring/include/mach/vmalloc.h +++ b/arch/arm/mach-bcmring/include/mach/vmalloc.h @@ -22,4 +22,4 @@ * 0xe0000000 to 0xefffffff. This gives us 256 MB of vm space and handles * larger physical memory designs better. */ -#define VMALLOC_END (PAGE_OFFSET + 0x30000000) +#define VMALLOC_END 0xf0000000 diff --git a/arch/arm/mach-clps711x/include/mach/vmalloc.h b/arch/arm/mach-clps711x/include/mach/vmalloc.h index ea6cc7b..30b3a287 100644 --- a/arch/arm/mach-clps711x/include/mach/vmalloc.h +++ b/arch/arm/mach-clps711x/include/mach/vmalloc.h @@ -17,4 +17,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 3d996b6..9be261b 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -769,8 +769,7 @@ static struct map_desc dm355_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00010000), .length = SZ_32K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 6b6f4c6..7781e35 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -969,8 +969,7 @@ static struct map_desc dm365_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00010000), .length = SZ_32K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 40fec31..5e5b0a7 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -653,8 +653,7 @@ static struct map_desc dm644x_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00008000), .length = SZ_16K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index e4a3df1..26e8a9c 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -737,8 +737,7 @@ static struct map_desc dm646x_io_desc[] = { .virtual = SRAM_VIRT, .pfn = __phys_to_pfn(0x00010000), .length = SZ_32K, - /* MT_MEMORY_NONCACHED requires supersection alignment */ - .type = MT_DEVICE, + .type = MT_MEMORY_NONCACHED, }, }; diff --git a/arch/arm/mach-dove/include/mach/io.h b/arch/arm/mach-dove/include/mach/io.h index 3b3e472..eb4936f 100644 --- a/arch/arm/mach-dove/include/mach/io.h +++ b/arch/arm/mach-dove/include/mach/io.h @@ -13,8 +13,8 @@ #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(((a) - DOVE_PCIE0_IO_PHYS_BASE) +\ - DOVE_PCIE0_IO_VIRT_BASE)) -#define __mem_pci(a) (a) +#define __io(a) ((void __iomem *)(((a) - DOVE_PCIE0_IO_BUS_BASE) + \ + DOVE_PCIE0_IO_VIRT_BASE)) +#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-ebsa110/include/mach/vmalloc.h b/arch/arm/mach-ebsa110/include/mach/vmalloc.h index 9b44c19..60bde56 100644 --- a/arch/arm/mach-ebsa110/include/mach/vmalloc.h +++ b/arch/arm/mach-ebsa110/include/mach/vmalloc.h @@ -7,4 +7,4 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define VMALLOC_END (PAGE_OFFSET + 0x1f000000) +#define VMALLOC_END 0xdf000000 diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c index 8904ca4..a696d35 100644 --- a/arch/arm/mach-ep93xx/dma-m2p.c +++ b/arch/arm/mach-ep93xx/dma-m2p.c @@ -276,7 +276,7 @@ static void channel_disable(struct m2p_channel *ch) v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN); m2p_set_control(ch, v); - while (m2p_channel_state(ch) == STATE_ON) + while (m2p_channel_state(ch) >= STATE_ON) cpu_relax(); m2p_set_control(ch, 0x0); diff --git a/arch/arm/mach-footbridge/include/mach/vmalloc.h b/arch/arm/mach-footbridge/include/mach/vmalloc.h index d0958d8..0ffbb7c 100644 --- a/arch/arm/mach-footbridge/include/mach/vmalloc.h +++ b/arch/arm/mach-footbridge/include/mach/vmalloc.h @@ -7,4 +7,4 @@ */ -#define VMALLOC_END (PAGE_OFFSET + 0x30000000) +#define VMALLOC_END 0xf0000000 diff --git a/arch/arm/mach-h720x/include/mach/vmalloc.h b/arch/arm/mach-h720x/include/mach/vmalloc.h index ff1460d..a45915b 100644 --- a/arch/arm/mach-h720x/include/mach/vmalloc.h +++ b/arch/arm/mach-h720x/include/mach/vmalloc.h @@ -5,6 +5,6 @@ #ifndef __ARCH_ARM_VMALLOC_H #define __ARCH_ARM_VMALLOC_H -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 #endif diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index 28f73a1..a1681fc 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -258,7 +258,7 @@ static void __init eukrea_cpuimx27_init(void) i2c_register_board_info(0, eukrea_cpuimx27_i2c_devices, ARRAY_SIZE(eukrea_cpuimx27_i2c_devices)); - imx27_add_imx_i2c(1, &cpuimx27_i2c1_data); + imx27_add_imx_i2c(0, &cpuimx27_i2c1_data); imx27_add_fec(NULL); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); diff --git a/arch/arm/mach-integrator/include/mach/vmalloc.h b/arch/arm/mach-integrator/include/mach/vmalloc.h index e87ab0b..e056e7c 100644 --- a/arch/arm/mach-integrator/include/mach/vmalloc.h +++ b/arch/arm/mach-integrator/include/mach/vmalloc.h @@ -17,4 +17,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 61cd4d6..24498a9 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -503,6 +503,14 @@ struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys) return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys); } +int dma_set_coherent_mask(struct device *dev, u64 mask) +{ + if (mask >= SZ_64M - 1) + return 0; + + return -EIO; +} + EXPORT_SYMBOL(ixp4xx_pci_read); EXPORT_SYMBOL(ixp4xx_pci_write); diff --git a/arch/arm/mach-ixp4xx/include/mach/hardware.h b/arch/arm/mach-ixp4xx/include/mach/hardware.h index f91ca6d..8138371 100644 --- a/arch/arm/mach-ixp4xx/include/mach/hardware.h +++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h @@ -26,6 +26,8 @@ #define PCIBIOS_MAX_MEM 0x4BFFFFFF #endif +#define ARCH_HAS_DMA_SET_COHERENT_MASK + #define pcibios_assign_all_busses() 1 /* Register locations and bits */ diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index cc25501..3410633 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -58,6 +58,12 @@ config MACH_TS41X QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS devices. +config MACH_DOCKSTAR + bool "Seagate FreeAgent DockStar" + help + Say 'Y' here if you want your kernel to support the + Seagate FreeAgent DockStar. + config MACH_OPENRD bool @@ -100,6 +106,12 @@ config MACH_NETSPACE_MAX_V2 Say 'Y' here if you want your kernel to support the LaCie Network Space Max v2 NAS. +config MACH_D2NET_V2 + bool "LaCie d2 Network v2 NAS Board" + help + Say 'Y' here if you want your kernel to support the + LaCie d2 Network v2 NAS. + config MACH_NET2BIG_V2 bool "LaCie 2Big Network v2 NAS Board" help diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index 295d7ba..5dcaa81 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -7,14 +7,16 @@ obj-$(CONFIG_MACH_MV88F6281GTW_GE) += mv88f6281gtw_ge-setup.o obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG) += sheevaplug-setup.o obj-$(CONFIG_MACH_GURUPLUG) += guruplug-setup.o +obj-$(CONFIG_MACH_DOCKSTAR) += dockstar-setup.o obj-$(CONFIG_MACH_TS219) += ts219-setup.o tsx1x-common.o obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o -obj-$(CONFIG_MACH_NETSPACE_V2) += netspace_v2-setup.o -obj-$(CONFIG_MACH_INETSPACE_V2) += netspace_v2-setup.o -obj-$(CONFIG_MACH_NETSPACE_MAX_V2) += netspace_v2-setup.o -obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o -obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o +obj-$(CONFIG_MACH_NETSPACE_V2) += netspace_v2-setup.o lacie_v2-common.o +obj-$(CONFIG_MACH_INETSPACE_V2) += netspace_v2-setup.o lacie_v2-common.o +obj-$(CONFIG_MACH_NETSPACE_MAX_V2) += netspace_v2-setup.o lacie_v2-common.o +obj-$(CONFIG_MACH_D2NET_V2) += d2net_v2-setup.o lacie_v2-common.o +obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o +obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o obj-$(CONFIG_MACH_T5325) += t5325-setup.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c new file mode 100644 index 0000000..cd62d0f --- /dev/null +++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c @@ -0,0 +1,231 @@ +/* + * arch/arm/mach-kirkwood/d2net_v2-setup.c + * + * LaCie d2 Network Space v2 Board Setup + * + * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/ata_platform.h> +#include <linux/mv643xx_eth.h> +#include <linux/input.h> +#include <linux/gpio.h> +#include <linux/gpio_keys.h> +#include <linux/leds.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <mach/kirkwood.h> +#include <mach/leds-ns2.h> +#include "common.h" +#include "mpp.h" +#include "lacie_v2-common.h" + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data d2net_v2_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ + +static struct mv_sata_platform_data d2net_v2_sata_data = { + .n_ports = 2, +}; + +/***************************************************************************** + * GPIO keys + ****************************************************************************/ + +#define D2NET_V2_GPIO_PUSH_BUTTON 34 +#define D2NET_V2_GPIO_POWER_SWITCH_ON 13 +#define D2NET_V2_GPIO_POWER_SWITCH_OFF 15 + +#define D2NET_V2_SWITCH_POWER_ON 0x1 +#define D2NET_V2_SWITCH_POWER_OFF 0x2 + +static struct gpio_keys_button d2net_v2_buttons[] = { + [0] = { + .type = EV_SW, + .code = D2NET_V2_SWITCH_POWER_ON, + .gpio = D2NET_V2_GPIO_POWER_SWITCH_ON, + .desc = "Back power switch (on|auto)", + .active_low = 0, + }, + [1] = { + .type = EV_SW, + .code = D2NET_V2_SWITCH_POWER_OFF, + .gpio = D2NET_V2_GPIO_POWER_SWITCH_OFF, + .desc = "Back power switch (auto|off)", + .active_low = 0, + }, + [2] = { + .code = KEY_POWER, + .gpio = D2NET_V2_GPIO_PUSH_BUTTON, + .desc = "Front Push Button", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data d2net_v2_button_data = { + .buttons = d2net_v2_buttons, + .nbuttons = ARRAY_SIZE(d2net_v2_buttons), +}; + +static struct platform_device d2net_v2_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &d2net_v2_button_data, + }, +}; + +/***************************************************************************** + * GPIO LEDs + ****************************************************************************/ + +#define D2NET_V2_GPIO_RED_LED 12 + +static struct gpio_led d2net_v2_gpio_led_pins[] = { + { + .name = "d2net_v2:red:fail", + .gpio = D2NET_V2_GPIO_RED_LED, + }, +}; + +static struct gpio_led_platform_data d2net_v2_gpio_leds_data = { + .num_leds = ARRAY_SIZE(d2net_v2_gpio_led_pins), + .leds = d2net_v2_gpio_led_pins, +}; + +static struct platform_device d2net_v2_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &d2net_v2_gpio_leds_data, + }, +}; + +/***************************************************************************** + * Dual-GPIO CPLD LEDs + ****************************************************************************/ + +#define D2NET_V2_GPIO_BLUE_LED_SLOW 29 +#define D2NET_V2_GPIO_BLUE_LED_CMD 30 + +static struct ns2_led d2net_v2_led_pins[] = { + { + .name = "d2net_v2:blue:sata", + .cmd = D2NET_V2_GPIO_BLUE_LED_CMD, + .slow = D2NET_V2_GPIO_BLUE_LED_SLOW, + }, +}; + +static struct ns2_led_platform_data d2net_v2_leds_data = { + .num_leds = ARRAY_SIZE(d2net_v2_led_pins), + .leds = d2net_v2_led_pins, +}; + +static struct platform_device d2net_v2_leds = { + .name = "leds-ns2", + .id = -1, + .dev = { + .platform_data = &d2net_v2_leds_data, + }, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static unsigned int d2net_v2_mpp_config[] __initdata = { + MPP0_SPI_SCn, + MPP1_SPI_MOSI, + MPP2_SPI_SCK, + MPP3_SPI_MISO, + MPP6_SYSRST_OUTn, + MPP7_GPO, /* Request power-off */ + MPP8_TW0_SDA, + MPP9_TW0_SCK, + MPP10_UART0_TXD, + MPP11_UART0_RXD, + MPP12_GPO, /* Red led */ + MPP13_GPIO, /* Rear power switch (on|auto) */ + MPP14_GPIO, /* USB fuse */ + MPP15_GPIO, /* Rear power switch (auto|off) */ + MPP16_GPIO, /* SATA 0 power */ + MPP21_SATA0_ACTn, + MPP24_GPIO, /* USB mode select */ + MPP26_GPIO, /* USB device vbus */ + MPP28_GPIO, /* USB enable host vbus */ + MPP29_GPIO, /* Blue led (slow register) */ + MPP30_GPIO, /* Blue led (command register) */ + MPP34_GPIO, /* Power button (1 = Released, 0 = Pushed) */ + MPP35_GPIO, /* Inhibit power-off */ + 0 +}; + +#define D2NET_V2_GPIO_POWER_OFF 7 + +static void d2net_v2_power_off(void) +{ + gpio_set_value(D2NET_V2_GPIO_POWER_OFF, 1); +} + +static void __init d2net_v2_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + kirkwood_mpp_conf(d2net_v2_mpp_config); + + lacie_v2_hdd_power_init(1); + + kirkwood_ehci_init(); + kirkwood_ge00_init(&d2net_v2_ge00_data); + kirkwood_sata_init(&d2net_v2_sata_data); + kirkwood_uart0_init(); + lacie_v2_register_flash(); + lacie_v2_register_i2c_devices(); + + platform_device_register(&d2net_v2_leds); + platform_device_register(&d2net_v2_gpio_leds); + platform_device_register(&d2net_v2_gpio_buttons); + + if (gpio_request(D2NET_V2_GPIO_POWER_OFF, "power-off") == 0 && + gpio_direction_output(D2NET_V2_GPIO_POWER_OFF, 0) == 0) + pm_power_off = d2net_v2_power_off; + else + pr_err("d2net_v2: failed to configure power-off GPIO\n"); +} + +MACHINE_START(D2NET_V2, "LaCie d2 Network v2") + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = d2net_v2_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &lacie_v2_timer, +MACHINE_END diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c new file mode 100644 index 0000000..a90475d --- /dev/null +++ b/arch/arm/mach-kirkwood/dockstar-setup.c @@ -0,0 +1,112 @@ +/* + * arch/arm/mach-kirkwood/dockstar-setup.c + * + * Seagate FreeAgent DockStar Setup + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/ata_platform.h> +#include <linux/mtd/partitions.h> +#include <linux/mv643xx_eth.h> +#include <linux/gpio.h> +#include <linux/leds.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <mach/kirkwood.h> +#include <plat/mvsdio.h> +#include "common.h" +#include "mpp.h" + +static struct mtd_partition dockstar_nand_parts[] = { + { + .name = "u-boot", + .offset = 0, + .size = SZ_1M + }, { + .name = "uImage", + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_4M + }, { + .name = "root", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL + }, +}; + +static struct mv643xx_eth_platform_data dockstar_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), +}; + +static struct gpio_led dockstar_led_pins[] = { + { + .name = "dockstar:green:health", + .default_trigger = "default-on", + .gpio = 46, + .active_low = 1, + }, + { + .name = "dockstar:orange:misc", + .default_trigger = "none", + .gpio = 47, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data dockstar_led_data = { + .leds = dockstar_led_pins, + .num_leds = ARRAY_SIZE(dockstar_led_pins), +}; + +static struct platform_device dockstar_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &dockstar_led_data, + } +}; + +static unsigned int dockstar_mpp_config[] __initdata = { + MPP29_GPIO, /* USB Power Enable */ + MPP46_GPIO, /* LED green */ + MPP47_GPIO, /* LED orange */ + 0 +}; + +static void __init dockstar_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + + /* setup gpio pin select */ + kirkwood_mpp_conf(dockstar_mpp_config); + + kirkwood_uart0_init(); + kirkwood_nand_init(ARRAY_AND_SIZE(dockstar_nand_parts), 25); + + if (gpio_request(29, "USB Power Enable") != 0 || + gpio_direction_output(29, 1) != 0) + printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n"); + kirkwood_ehci_init(); + + kirkwood_ge00_init(&dockstar_ge00_data); + + platform_device_register(&dockstar_leds); +} + +MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar") + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = dockstar_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &kirkwood_timer, +MACHINE_END diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index 93fc2ec..6e924b3 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -38,7 +38,7 @@ #define KIRKWOOD_PCIE1_IO_PHYS_BASE 0xf3000000 #define KIRKWOOD_PCIE1_IO_VIRT_BASE 0xfef00000 -#define KIRKWOOD_PCIE1_IO_BUS_BASE 0x00000000 +#define KIRKWOOD_PCIE1_IO_BUS_BASE 0x00100000 #define KIRKWOOD_PCIE1_IO_SIZE SZ_1M #define KIRKWOOD_PCIE_IO_PHYS_BASE 0xf2000000 diff --git a/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h new file mode 100644 index 0000000..24b536e --- /dev/null +++ b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h @@ -0,0 +1,55 @@ +/* + * arch/arm/mach-kirkwood/include/mach/leds-netxbig.h + * + * Platform data structure for netxbig LED driver + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_LEDS_NETXBIG_H +#define __MACH_LEDS_NETXBIG_H + +struct netxbig_gpio_ext { + unsigned *addr; + int num_addr; + unsigned *data; + int num_data; + unsigned enable; +}; + +enum netxbig_led_mode { + NETXBIG_LED_OFF, + NETXBIG_LED_ON, + NETXBIG_LED_SATA, + NETXBIG_LED_TIMER1, + NETXBIG_LED_TIMER2, + NETXBIG_LED_MODE_NUM, +}; + +#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM + +struct netxbig_led_timer { + unsigned long delay_on; + unsigned long delay_off; + enum netxbig_led_mode mode; +}; + +struct netxbig_led { + const char *name; + const char *default_trigger; + int mode_addr; + int *mode_val; + int bright_addr; +}; + +struct netxbig_led_platform_data { + struct netxbig_gpio_ext *gpio_ext; + struct netxbig_led_timer *timer; + int num_timer; + struct netxbig_led *leds; + int num_leds; +}; + +#endif /* __MACH_LEDS_NETXBIG_H */ diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.c b/arch/arm/mach-kirkwood/lacie_v2-common.c new file mode 100644 index 0000000..d3ea1b6 --- /dev/null +++ b/arch/arm/mach-kirkwood/lacie_v2-common.c @@ -0,0 +1,127 @@ +/* + * arch/arm/mach-kirkwood/lacie_v2-common.c + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mtd/physmap.h> +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> +#include <linux/i2c/at24.h> +#include <linux/gpio.h> +#include <asm/mach/time.h> +#include <mach/kirkwood.h> +#include <mach/irqs.h> +#include <plat/time.h> +#include "common.h" + +/***************************************************************************** + * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) + ****************************************************************************/ + +static struct mtd_partition lacie_v2_flash_parts[] = { + { + .name = "u-boot", + .size = MTDPART_SIZ_FULL, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, +}; + +static const struct flash_platform_data lacie_v2_flash = { + .type = "mx25l4005a", + .name = "spi_flash", + .parts = lacie_v2_flash_parts, + .nr_parts = ARRAY_SIZE(lacie_v2_flash_parts), +}; + +static struct spi_board_info __initdata lacie_v2_spi_slave_info[] = { + { + .modalias = "m25p80", + .platform_data = &lacie_v2_flash, + .irq = -1, + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + }, +}; + +void __init lacie_v2_register_flash(void) +{ + spi_register_board_info(lacie_v2_spi_slave_info, + ARRAY_SIZE(lacie_v2_spi_slave_info)); + kirkwood_spi_init(); +} + +/***************************************************************************** + * I2C devices + ****************************************************************************/ + +static struct at24_platform_data at24c04 = { + .byte_len = SZ_4K / 8, + .page_size = 16, +}; + +/* + * i2c addr | chip | description + * 0x50 | HT24LC04 | eeprom (512B) + */ + +static struct i2c_board_info __initdata lacie_v2_i2c_info[] = { + { + I2C_BOARD_INFO("24c04", 0x50), + .platform_data = &at24c04, + } +}; + +void __init lacie_v2_register_i2c_devices(void) +{ + kirkwood_i2c_init(); + i2c_register_board_info(0, lacie_v2_i2c_info, + ARRAY_SIZE(lacie_v2_i2c_info)); +} + +/***************************************************************************** + * Hard Disk power + ****************************************************************************/ + +static int __initdata lacie_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 }; + +void __init lacie_v2_hdd_power_init(int hdd_num) +{ + int i; + int err; + + /* Power up all hard disks. */ + for (i = 0; i < hdd_num; i++) { + err = gpio_request(lacie_v2_gpio_hdd_power[i], NULL); + if (err == 0) { + err = gpio_direction_output( + lacie_v2_gpio_hdd_power[i], 1); + /* Free the HDD power GPIOs. This allow user-space to + * configure them via the gpiolib sysfs interface. */ + gpio_free(lacie_v2_gpio_hdd_power[i]); + } + if (err) + pr_err("Failed to power up HDD%d\n", i + 1); + } +} + +/***************************************************************************** + * Timer + ****************************************************************************/ + +static void lacie_v2_timer_init(void) +{ + kirkwood_tclk = 166666667; + orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); +} + +struct sys_timer lacie_v2_timer = { + .init = lacie_v2_timer_init, +}; diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.h b/arch/arm/mach-kirkwood/lacie_v2-common.h new file mode 100644 index 0000000..af52131 --- /dev/null +++ b/arch/arm/mach-kirkwood/lacie_v2-common.h @@ -0,0 +1,18 @@ +/* + * arch/arm/mach-kirkwood/lacie_v2-common.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ARCH_KIRKWOOD_LACIE_V2_COMMON_H +#define __ARCH_KIRKWOOD_LACIE_V2_COMMON_H + +void lacie_v2_register_flash(void); +void lacie_v2_register_i2c_devices(void); +void lacie_v2_hdd_power_init(int hdd_num); + +extern struct sys_timer lacie_v2_timer; + +#endif diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c index d26bf32..fed264d 100644 --- a/arch/arm/mach-kirkwood/netspace_v2-setup.c +++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c @@ -24,56 +24,19 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/mtd/physmap.h> -#include <linux/spi/flash.h> -#include <linux/spi/spi.h> #include <linux/ata_platform.h> #include <linux/mv643xx_eth.h> -#include <linux/i2c.h> -#include <linux/i2c/at24.h> #include <linux/input.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> #include <linux/leds.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/time.h> #include <mach/kirkwood.h> #include <mach/leds-ns2.h> -#include <plat/time.h> #include "common.h" #include "mpp.h" - -/***************************************************************************** - * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) - ****************************************************************************/ - -static struct mtd_partition netspace_v2_flash_parts[] = { - { - .name = "u-boot", - .size = MTDPART_SIZ_FULL, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, -}; - -static const struct flash_platform_data netspace_v2_flash = { - .type = "mx25l4005a", - .name = "spi_flash", - .parts = netspace_v2_flash_parts, - .nr_parts = ARRAY_SIZE(netspace_v2_flash_parts), -}; - -static struct spi_board_info __initdata netspace_v2_spi_slave_info[] = { - { - .modalias = "m25p80", - .platform_data = &netspace_v2_flash, - .irq = -1, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 0, - }, -}; +#include "lacie_v2-common.h" /***************************************************************************** * Ethernet @@ -84,27 +47,6 @@ static struct mv643xx_eth_platform_data netspace_v2_ge00_data = { }; /***************************************************************************** - * I2C devices - ****************************************************************************/ - -static struct at24_platform_data at24c04 = { - .byte_len = SZ_4K / 8, - .page_size = 16, -}; - -/* - * i2c addr | chip | description - * 0x50 | HT24LC04 | eeprom (512B) - */ - -static struct i2c_board_info __initdata netspace_v2_i2c_info[] = { - { - I2C_BOARD_INFO("24c04", 0x50), - .platform_data = &at24c04, - } -}; - -/***************************************************************************** * SATA ****************************************************************************/ @@ -112,35 +54,6 @@ static struct mv_sata_platform_data netspace_v2_sata_data = { .n_ports = 2, }; -#define NETSPACE_V2_GPIO_SATA0_POWER 16 -#define NETSPACE_V2_GPIO_SATA1_POWER 17 - -static void __init netspace_v2_sata_power_init(void) -{ - int err; - - err = gpio_request(NETSPACE_V2_GPIO_SATA0_POWER, "SATA0 power"); - if (err == 0) { - err = gpio_direction_output(NETSPACE_V2_GPIO_SATA0_POWER, 1); - if (err) - gpio_free(NETSPACE_V2_GPIO_SATA0_POWER); - } - if (err) - pr_err("netspace_v2: failed to setup SATA0 power\n"); - - if (machine_is_netspace_max_v2()) { - err = gpio_request(NETSPACE_V2_GPIO_SATA1_POWER, "SATA1 power"); - if (err == 0) { - err = gpio_direction_output( - NETSPACE_V2_GPIO_SATA1_POWER, 1); - if (err) - gpio_free(NETSPACE_V2_GPIO_SATA1_POWER); - } - if (err) - pr_err("netspace_v2: failed to setup SATA1 power\n"); - } -} - /***************************************************************************** * GPIO keys ****************************************************************************/ @@ -224,20 +137,6 @@ static struct platform_device netspace_v2_leds = { }; /***************************************************************************** - * Timer - ****************************************************************************/ - -static void netspace_v2_timer_init(void) -{ - kirkwood_tclk = 166666667; - orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); -} - -struct sys_timer netspace_v2_timer = { - .init = netspace_v2_timer_init, -}; - -/***************************************************************************** * General Setup ****************************************************************************/ @@ -291,18 +190,17 @@ static void __init netspace_v2_init(void) kirkwood_init(); kirkwood_mpp_conf(netspace_v2_mpp_config); - netspace_v2_sata_power_init(); + if (machine_is_netspace_max_v2()) + lacie_v2_hdd_power_init(2); + else + lacie_v2_hdd_power_init(1); kirkwood_ehci_init(); kirkwood_ge00_init(&netspace_v2_ge00_data); kirkwood_sata_init(&netspace_v2_sata_data); kirkwood_uart0_init(); - spi_register_board_info(netspace_v2_spi_slave_info, - ARRAY_SIZE(netspace_v2_spi_slave_info)); - kirkwood_spi_init(); - kirkwood_i2c_init(); - i2c_register_board_info(0, netspace_v2_i2c_info, - ARRAY_SIZE(netspace_v2_i2c_info)); + lacie_v2_register_flash(); + lacie_v2_register_i2c_devices(); platform_device_register(&netspace_v2_leds); platform_device_register(&netspace_v2_gpio_leds); @@ -323,7 +221,7 @@ MACHINE_START(NETSPACE_V2, "LaCie Network Space v2") .init_machine = netspace_v2_init, .map_io = kirkwood_map_io, .init_irq = kirkwood_init_irq, - .timer = &netspace_v2_timer, + .timer = &lacie_v2_timer, MACHINE_END #endif @@ -335,7 +233,7 @@ MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2") .init_machine = netspace_v2_init, .map_io = kirkwood_map_io, .init_irq = kirkwood_init_irq, - .timer = &netspace_v2_timer, + .timer = &lacie_v2_timer, MACHINE_END #endif @@ -347,6 +245,6 @@ MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2") .init_machine = netspace_v2_init, .map_io = kirkwood_map_io, .init_irq = kirkwood_init_irq, - .timer = &netspace_v2_timer, + .timer = &lacie_v2_timer, MACHINE_END #endif diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c index 2bd14c5..d970e1e 100644 --- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c +++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c @@ -23,55 +23,19 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/mtd/physmap.h> -#include <linux/spi/flash.h> -#include <linux/spi/spi.h> #include <linux/ata_platform.h> #include <linux/mv643xx_eth.h> -#include <linux/i2c.h> -#include <linux/i2c/at24.h> #include <linux/input.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> #include <linux/leds.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/time.h> #include <mach/kirkwood.h> -#include <plat/time.h> +#include <mach/leds-netxbig.h> #include "common.h" #include "mpp.h" - -/***************************************************************************** - * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) - ****************************************************************************/ - -static struct mtd_partition netxbig_v2_flash_parts[] = { - { - .name = "u-boot", - .size = MTDPART_SIZ_FULL, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, -}; - -static const struct flash_platform_data netxbig_v2_flash = { - .type = "mx25l4005a", - .name = "spi_flash", - .parts = netxbig_v2_flash_parts, - .nr_parts = ARRAY_SIZE(netxbig_v2_flash_parts), -}; - -static struct spi_board_info __initdata netxbig_v2_spi_slave_info[] = { - { - .modalias = "m25p80", - .platform_data = &netxbig_v2_flash, - .irq = -1, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 0, - }, -}; +#include "lacie_v2-common.h" /***************************************************************************** * Ethernet @@ -86,27 +50,6 @@ static struct mv643xx_eth_platform_data netxbig_v2_ge01_data = { }; /***************************************************************************** - * I2C devices - ****************************************************************************/ - -static struct at24_platform_data at24c04 = { - .byte_len = SZ_4K / 8, - .page_size = 16, -}; - -/* - * i2c addr | chip | description - * 0x50 | HT24LC04 | eeprom (512B) - */ - -static struct i2c_board_info __initdata netxbig_v2_i2c_info[] = { - { - I2C_BOARD_INFO("24c04", 0x50), - .platform_data = &at24c04, - } -}; - -/***************************************************************************** * SATA ****************************************************************************/ @@ -114,34 +57,6 @@ static struct mv_sata_platform_data netxbig_v2_sata_data = { .n_ports = 2, }; -static int __initdata netxbig_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 }; - -static void __init netxbig_v2_sata_power_init(void) -{ - int i; - int err; - int hdd_nb; - - if (machine_is_net2big_v2()) - hdd_nb = 2; - else - hdd_nb = 5; - - /* Power up all hard disks. */ - for (i = 0; i < hdd_nb; i++) { - err = gpio_request(netxbig_v2_gpio_hdd_power[i], NULL); - if (err == 0) { - err = gpio_direction_output( - netxbig_v2_gpio_hdd_power[i], 1); - /* Free the HDD power GPIOs. This allow user-space to - * configure them via the gpiolib sysfs interface. */ - gpio_free(netxbig_v2_gpio_hdd_power[i]); - } - if (err) - pr_err("netxbig_v2: failed to power up HDD%d\n", i + 1); - } -} - /***************************************************************************** * GPIO keys ****************************************************************************/ @@ -190,7 +105,7 @@ static struct platform_device netxbig_v2_gpio_buttons = { }; /***************************************************************************** - * GPIO LEDs + * GPIO extension LEDs ****************************************************************************/ /* @@ -200,19 +115,32 @@ static struct platform_device netxbig_v2_gpio_buttons = { * - address register : bit [0-2] -> GPIO [47-49] * - data register : bit [0-2] -> GPIO [44-46] * - enable register : GPIO 29 - * + */ + +static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 }; +static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 }; + +static struct netxbig_gpio_ext netxbig_v2_gpio_ext = { + .addr = netxbig_v2_gpio_ext_addr, + .num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr), + .data = netxbig_v2_gpio_ext_data, + .num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data), + .enable = 29, +}; + +/* * Address register selection: * * addr | register * ---------------------------- * 0 | front LED * 1 | front LED brightness - * 2 | HDD LED brightness - * 3 | HDD1 LED - * 4 | HDD2 LED - * 5 | HDD3 LED - * 6 | HDD4 LED - * 7 | HDD5 LED + * 2 | SATA LED brightness + * 3 | SATA0 LED + * 4 | SATA1 LED + * 5 | SATA2 LED + * 6 | SATA3 LED + * 7 | SATA4 LED * * Data register configuration: * @@ -233,30 +161,107 @@ static struct platform_device netxbig_v2_gpio_buttons = { * 6 | blink blue on=1 sec and red on=1 sec * 7 | blink blue on=0.5 sec and blue off=2.5 sec * - * data | HDD LED mode + * data | SATA LED mode * ------------------------------------------------- - * 0 | fix blue on + * 0 | fix off * 1 | SATA activity blink * 2 | fix red on * 3 | blink blue on=1 sec and blue off=1 sec * 4 | blink red on=1 sec and red off=1 sec * 5 | blink blue on=2.5 sec and red on=0.5 sec * 6 | blink blue on=1 sec and red on=1 sec - * 7 | blink blue on=0.5 sec and blue off=2.5 sec + * 7 | fix blue on */ -/***************************************************************************** - * Timer - ****************************************************************************/ +static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = { + [NETXBIG_LED_OFF] = 0, + [NETXBIG_LED_ON] = 2, + [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE, + [NETXBIG_LED_TIMER1] = 4, + [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE, +}; -static void netxbig_v2_timer_init(void) -{ - kirkwood_tclk = 166666667; - orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); -} +static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = { + [NETXBIG_LED_OFF] = 0, + [NETXBIG_LED_ON] = 1, + [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE, + [NETXBIG_LED_TIMER1] = 3, + [NETXBIG_LED_TIMER2] = 7, +}; + +static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = { + [NETXBIG_LED_OFF] = 0, + [NETXBIG_LED_ON] = 7, + [NETXBIG_LED_SATA] = 1, + [NETXBIG_LED_TIMER1] = 3, + [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE, +}; + +static struct netxbig_led_timer netxbig_v2_led_timer[] = { + [0] = { + .delay_on = 500, + .delay_off = 500, + .mode = NETXBIG_LED_TIMER1, + }, + [1] = { + .delay_on = 500, + .delay_off = 1000, + .mode = NETXBIG_LED_TIMER2, + }, +}; + +#define NETXBIG_LED(_name, maddr, mval, baddr) \ + { .name = _name, \ + .mode_addr = maddr, \ + .mode_val = mval, \ + .bright_addr = baddr } + +static struct netxbig_led net2big_v2_leds_ctrl[] = { + NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1), + NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1), + NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2), + NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2), + NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2), + NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2), +}; + +static struct netxbig_led_platform_data net2big_v2_leds_data = { + .gpio_ext = &netxbig_v2_gpio_ext, + .timer = netxbig_v2_led_timer, + .num_timer = ARRAY_SIZE(netxbig_v2_led_timer), + .leds = net2big_v2_leds_ctrl, + .num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl), +}; + +static struct netxbig_led net5big_v2_leds_ctrl[] = { + NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1), + NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1), + NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2), + NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2), + NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2), + NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2), + NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2), + NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2), + NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2), + NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2), + NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2), + NETXBIG_LED("net5big-v2:red:sata5", 7, netxbig_v2_red_mled, 2), +}; -struct sys_timer netxbig_v2_timer = { - .init = netxbig_v2_timer_init, +static struct netxbig_led_platform_data net5big_v2_leds_data = { + .gpio_ext = &netxbig_v2_gpio_ext, + .timer = netxbig_v2_led_timer, + .num_timer = ARRAY_SIZE(netxbig_v2_led_timer), + .leds = net5big_v2_leds_ctrl, + .num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl), +}; + +static struct platform_device netxbig_v2_leds = { + .name = "leds-netxbig", + .id = -1, + .dev = { + .platform_data = &net2big_v2_leds_data, + }, }; /***************************************************************************** @@ -284,18 +289,18 @@ static unsigned int net2big_v2_mpp_config[] __initdata = { MPP24_GPIO, /* USB mode select */ MPP26_GPIO, /* USB device vbus */ MPP28_GPIO, /* USB enable host vbus */ - MPP29_GPIO, /* CPLD extension ALE */ + MPP29_GPIO, /* GPIO extension ALE */ MPP34_GPIO, /* Rear Push button */ MPP35_GPIO, /* Inhibit switch power-off */ MPP36_GPIO, /* SATA HDD1 presence */ MPP37_GPIO, /* SATA HDD2 presence */ MPP40_GPIO, /* eSATA presence */ - MPP44_GPIO, /* CPLD extension (data 0) */ - MPP45_GPIO, /* CPLD extension (data 1) */ - MPP46_GPIO, /* CPLD extension (data 2) */ - MPP47_GPIO, /* CPLD extension (addr 0) */ - MPP48_GPIO, /* CPLD extension (addr 1) */ - MPP49_GPIO, /* CPLD extension (addr 2) */ + MPP44_GPIO, /* GPIO extension (data 0) */ + MPP45_GPIO, /* GPIO extension (data 1) */ + MPP46_GPIO, /* GPIO extension (data 2) */ + MPP47_GPIO, /* GPIO extension (addr 0) */ + MPP48_GPIO, /* GPIO extension (addr 1) */ + MPP49_GPIO, /* GPIO extension (addr 2) */ 0 }; @@ -324,7 +329,7 @@ static unsigned int net5big_v2_mpp_config[] __initdata = { MPP26_GE1_RXD2, MPP27_GE1_RXD3, MPP28_GPIO, /* USB enable host vbus */ - MPP29_GPIO, /* CPLD extension ALE */ + MPP29_GPIO, /* GPIO extension ALE */ MPP30_GE1_RXCTL, MPP31_GE1_RXCLK, MPP32_GE1_TCLKOUT, @@ -339,12 +344,12 @@ static unsigned int net5big_v2_mpp_config[] __initdata = { MPP41_GPIO, /* SATA HDD3 power */ MPP42_GPIO, /* SATA HDD4 power */ MPP43_GPIO, /* SATA HDD5 power */ - MPP44_GPIO, /* CPLD extension (data 0) */ - MPP45_GPIO, /* CPLD extension (data 1) */ - MPP46_GPIO, /* CPLD extension (data 2) */ - MPP47_GPIO, /* CPLD extension (addr 0) */ - MPP48_GPIO, /* CPLD extension (addr 1) */ - MPP49_GPIO, /* CPLD extension (addr 2) */ + MPP44_GPIO, /* GPIO extension (data 0) */ + MPP45_GPIO, /* GPIO extension (data 1) */ + MPP46_GPIO, /* GPIO extension (data 2) */ + MPP47_GPIO, /* GPIO extension (addr 0) */ + MPP48_GPIO, /* GPIO extension (addr 1) */ + MPP49_GPIO, /* GPIO extension (addr 2) */ 0 }; @@ -366,7 +371,10 @@ static void __init netxbig_v2_init(void) else kirkwood_mpp_conf(net5big_v2_mpp_config); - netxbig_v2_sata_power_init(); + if (machine_is_net2big_v2()) + lacie_v2_hdd_power_init(2); + else + lacie_v2_hdd_power_init(5); kirkwood_ehci_init(); kirkwood_ge00_init(&netxbig_v2_ge00_data); @@ -374,13 +382,12 @@ static void __init netxbig_v2_init(void) kirkwood_ge01_init(&netxbig_v2_ge01_data); kirkwood_sata_init(&netxbig_v2_sata_data); kirkwood_uart0_init(); - spi_register_board_info(netxbig_v2_spi_slave_info, - ARRAY_SIZE(netxbig_v2_spi_slave_info)); - kirkwood_spi_init(); - kirkwood_i2c_init(); - i2c_register_board_info(0, netxbig_v2_i2c_info, - ARRAY_SIZE(netxbig_v2_i2c_info)); + lacie_v2_register_flash(); + lacie_v2_register_i2c_devices(); + if (machine_is_net5big_v2()) + netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data; + platform_device_register(&netxbig_v2_leds); platform_device_register(&netxbig_v2_gpio_buttons); if (gpio_request(NETXBIG_V2_GPIO_POWER_OFF, "power-off") == 0 && @@ -398,7 +405,7 @@ MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2") .init_machine = netxbig_v2_init, .map_io = kirkwood_map_io, .init_irq = kirkwood_init_irq, - .timer = &netxbig_v2_timer, + .timer = &lacie_v2_timer, MACHINE_END #endif @@ -410,6 +417,6 @@ MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2") .init_machine = netxbig_v2_init, .map_io = kirkwood_map_io, .init_irq = kirkwood_init_irq, - .timer = &netxbig_v2_timer, + .timer = &lacie_v2_timer, MACHINE_END #endif diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c index fd06be6..38017c8 100644 --- a/arch/arm/mach-kirkwood/openrd-setup.c +++ b/arch/arm/mach-kirkwood/openrd-setup.c @@ -16,6 +16,7 @@ #include <linux/ata_platform.h> #include <linux/mv643xx_eth.h> #include <linux/i2c.h> +#include <linux/gpio.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/kirkwood.h> @@ -57,7 +58,22 @@ static struct mvsdio_platform_data openrd_mvsdio_data = { }; static unsigned int openrd_mpp_config[] __initdata = { + MPP12_SD_CLK, + MPP13_SD_CMD, + MPP14_SD_D0, + MPP15_SD_D1, + MPP16_SD_D2, + MPP17_SD_D3, + MPP28_GPIO, MPP29_GPIO, + MPP34_GPIO, + 0 +}; + +/* Configure MPP for UART1 */ +static unsigned int openrd_uart1_mpp_config[] __initdata = { + MPP13_UART1_TXD, + MPP14_UART1_RXD, 0 }; @@ -67,6 +83,68 @@ static struct i2c_board_info i2c_board_info[] __initdata = { }, }; +static int __initdata uart1; + +static int __init sd_uart_selection(char *str) +{ + uart1 = -EINVAL; + + /* Default is SD. Change if required, for UART */ + if (!str) + return 0; + + if (!strncmp(str, "232", 3)) { + uart1 = 232; + } else if (!strncmp(str, "485", 3)) { + /* OpenRD-Base doesn't have RS485. Treat is as an + * unknown argument & just have default setting - + * which is SD */ + if (machine_is_openrd_base()) { + uart1 = -ENODEV; + return 1; + } + + uart1 = 485; + } + return 1; +} +/* Parse boot_command_line string kw_openrd_init_uart1=232/485 */ +__setup("kw_openrd_init_uart1=", sd_uart_selection); + +static int __init uart1_mpp_config(void) +{ + kirkwood_mpp_conf(openrd_uart1_mpp_config); + + if (gpio_request(34, "SD_UART1_SEL")) { + printk(KERN_ERR "GPIO request failed for SD/UART1 selection" + ", gpio: 34\n"); + return -EIO; + } + + if (gpio_request(28, "RS232_RS485_SEL")) { + printk(KERN_ERR "GPIO request failed for RS232/RS485 selection" + ", gpio# 28\n"); + gpio_free(34); + return -EIO; + } + + /* Select UART1 + * Pin # 34: 0 => UART1, 1 => SD */ + gpio_direction_output(34, 0); + + /* Select RS232 OR RS485 + * Pin # 28: 0 => RS232, 1 => RS485 */ + if (uart1 == 232) + gpio_direction_output(28, 0); + else + gpio_direction_output(28, 1); + + gpio_free(34); + gpio_free(28); + + return 0; +} + static void __init openrd_init(void) { /* @@ -90,7 +168,6 @@ static void __init openrd_init(void) kirkwood_ge01_init(&openrd_ge01_data); kirkwood_sata_init(&openrd_sata_data); - kirkwood_sdio_init(&openrd_mvsdio_data); kirkwood_i2c_init(); @@ -99,6 +176,28 @@ static void __init openrd_init(void) ARRAY_SIZE(i2c_board_info)); kirkwood_audio_init(); } + + if (uart1 <= 0) { + if (uart1 < 0) + printk(KERN_ERR "Invalid kernel parameter to select " + "UART1. Defaulting to SD. ERROR CODE: %d\n", + uart1); + + /* Select SD + * Pin # 34: 0 => UART1, 1 => SD */ + if (gpio_request(34, "SD_UART1_SEL")) { + printk(KERN_ERR "GPIO request failed for SD/UART1 " + "selection, gpio: 34\n"); + } else { + + gpio_direction_output(34, 1); + gpio_free(34); + kirkwood_sdio_init(&openrd_mvsdio_data); + } + } else { + if (!uart1_mpp_config()) + kirkwood_uart1_init(); + } } static int __init openrd_pci_init(void) diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index 55e7f00..513ad31 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -117,7 +117,7 @@ static void __init pcie0_ioresources_init(struct pcie_port *pp) * IORESOURCE_IO */ pp->res[0].name = "PCIe 0 I/O Space"; - pp->res[0].start = KIRKWOOD_PCIE_IO_PHYS_BASE; + pp->res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE; pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1; pp->res[0].flags = IORESOURCE_IO; @@ -139,7 +139,7 @@ static void __init pcie1_ioresources_init(struct pcie_port *pp) * IORESOURCE_IO */ pp->res[0].name = "PCIe 1 I/O Space"; - pp->res[0].start = KIRKWOOD_PCIE1_IO_PHYS_BASE; + pp->res[0].start = KIRKWOOD_PCIE1_IO_BUS_BASE; pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1; pp->res[0].flags = IORESOURCE_IO; diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index 6ab843e..0711d3b 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -57,6 +57,13 @@ config MACH_MARVELL_JASPER PXA910-based development board. Since MMP2 is compatible to ARMv6 architecture. +config MACH_TETON_BGA + bool "Marvell's PXA168 Teton BGA Development Board" + select CPU_PXA168 + help + Say 'Y' here if you want to support the Marvell PXA168-based + Teton BGA Development Board. + endmenu config CPU_PXA168 diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile index 8b66d06..751cdbf 100644 --- a/arch/arm/mach-mmp/Makefile +++ b/arch/arm/mach-mmp/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o obj-$(CONFIG_MACH_TTC_DKB) += ttc_dkb.o obj-$(CONFIG_MACH_FLINT) += flint.o obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o +obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 0629394..4681bed 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -16,6 +16,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> +#include <linux/interrupt.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -23,6 +24,9 @@ #include <mach/mfp-pxa168.h> #include <mach/pxa168.h> #include <mach/gpio.h> +#include <video/pxa168fb.h> +#include <linux/input.h> +#include <plat/pxa27x_keypad.h> #include "common.h" @@ -66,6 +70,43 @@ static unsigned long common_pin_config[] __initdata = { GPIO115_I2S_BCLK, GPIO116_I2S_RXD, GPIO117_I2S_TXD, + + /* LCD */ + GPIO56_LCD_FCLK_RD, + GPIO57_LCD_LCLK_A0, + GPIO58_LCD_PCLK_WR, + GPIO59_LCD_DENA_BIAS, + GPIO60_LCD_DD0, + GPIO61_LCD_DD1, + GPIO62_LCD_DD2, + GPIO63_LCD_DD3, + GPIO64_LCD_DD4, + GPIO65_LCD_DD5, + GPIO66_LCD_DD6, + GPIO67_LCD_DD7, + GPIO68_LCD_DD8, + GPIO69_LCD_DD9, + GPIO70_LCD_DD10, + GPIO71_LCD_DD11, + GPIO72_LCD_DD12, + GPIO73_LCD_DD13, + GPIO74_LCD_DD14, + GPIO75_LCD_DD15, + GPIO76_LCD_DD16, + GPIO77_LCD_DD17, + GPIO78_LCD_DD18, + GPIO79_LCD_DD19, + GPIO80_LCD_DD20, + GPIO81_LCD_DD21, + GPIO82_LCD_DD22, + GPIO83_LCD_DD23, + + /* Keypad */ + GPIO109_KP_MKIN1, + GPIO110_KP_MKIN0, + GPIO111_KP_MKOUT7, + GPIO112_KP_MKOUT6, + GPIO121_KP_MKIN4, }; static struct smc91x_platdata smc91x_info = { @@ -134,6 +175,51 @@ static struct i2c_board_info aspenite_i2c_info[] __initdata = { { I2C_BOARD_INFO("wm8753", 0x1b), }, }; +static struct fb_videomode video_modes[] = { + [0] = { + .pixclock = 30120, + .refresh = 60, + .xres = 800, + .yres = 480, + .hsync_len = 1, + .left_margin = 215, + .right_margin = 40, + .vsync_len = 1, + .upper_margin = 34, + .lower_margin = 10, + .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, + }, +}; + +struct pxa168fb_mach_info aspenite_lcd_info = { + .id = "Graphic Frame", + .modes = video_modes, + .num_modes = ARRAY_SIZE(video_modes), + .pix_fmt = PIX_FMT_RGB565, + .io_pin_allocation_mode = PIN_MODE_DUMB_24, + .dumb_mode = DUMB_MODE_RGB888, + .active = 1, + .panel_rbswap = 0, + .invert_pixclock = 0, +}; + +static unsigned int aspenite_matrix_key_map[] = { + KEY(0, 6, KEY_UP), /* SW 4 */ + KEY(0, 7, KEY_DOWN), /* SW 5 */ + KEY(1, 6, KEY_LEFT), /* SW 6 */ + KEY(1, 7, KEY_RIGHT), /* SW 7 */ + KEY(4, 6, KEY_ENTER), /* SW 8 */ + KEY(4, 7, KEY_ESC), /* SW 9 */ +}; + +static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = { + .matrix_key_rows = 5, + .matrix_key_cols = 8, + .matrix_key_map = aspenite_matrix_key_map, + .matrix_key_map_size = ARRAY_SIZE(aspenite_matrix_key_map), + .debounce_interval = 30, +}; + static void __init common_init(void) { mfp_config(ARRAY_AND_SIZE(common_pin_config)); @@ -143,6 +229,8 @@ static void __init common_init(void) pxa168_add_twsi(1, NULL, ARRAY_AND_SIZE(aspenite_i2c_info)); pxa168_add_ssp(1); pxa168_add_nand(&aspenite_nand_info); + pxa168_add_fb(&aspenite_lcd_info); + pxa168_add_keypad(&aspenite_keypad_info); /* off-chip devices */ platform_device_register(&smc91x_device); @@ -152,6 +240,7 @@ MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform") .phys_io = APB_PHYS_BASE, .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, .map_io = mmp_map_io, + .nr_irqs = IRQ_BOARD_START, .init_irq = pxa168_init_irq, .timer = &pxa168_timer, .init_machine = common_init, @@ -161,6 +250,7 @@ MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform") .phys_io = APB_PHYS_BASE, .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, .map_io = mmp_map_io, + .nr_irqs = IRQ_BOARD_START, .init_irq = pxa168_init_irq, .timer = &pxa168_timer, .init_machine = common_init, diff --git a/arch/arm/mach-mmp/common.c b/arch/arm/mach-mmp/common.c index 3b29fa7..0ec0ca8 100644 --- a/arch/arm/mach-mmp/common.c +++ b/arch/arm/mach-mmp/common.c @@ -10,13 +10,20 @@ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/module.h> #include <asm/page.h> #include <asm/mach/map.h> #include <mach/addr-map.h> +#include <mach/cputype.h> #include "common.h" +#define MMP_CHIPID (AXI_VIRT_BASE + 0x82c00) + +unsigned int mmp_chip_id; +EXPORT_SYMBOL(mmp_chip_id); + static struct map_desc standard_io_desc[] __initdata = { { .pfn = __phys_to_pfn(APB_PHYS_BASE), @@ -34,4 +41,7 @@ static struct map_desc standard_io_desc[] __initdata = { void __init mmp_map_io(void) { iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); + + /* this is early, initialize mmp_chip_id here */ + mmp_chip_id = __raw_readl(MMP_CHIPID); } diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c index e4312d2..c558425 100644 --- a/arch/arm/mach-mmp/flint.c +++ b/arch/arm/mach-mmp/flint.c @@ -16,6 +16,7 @@ #include <linux/smc91x.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/interrupt.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -25,6 +26,8 @@ #include "common.h" +#define FLINT_NR_IRQS (IRQ_BOARD_START + 48) + static unsigned long flint_pin_config[] __initdata = { /* UART1 */ GPIO45_UART1_RXD, @@ -116,6 +119,7 @@ MACHINE_START(FLINT, "Flint Development Platform") .phys_io = APB_PHYS_BASE, .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, .map_io = mmp_map_io, + .nr_irqs = FLINT_NR_IRQS, .init_irq = mmp2_init_irq, .timer = &mmp2_timer, .init_machine = flint_init, diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h index 83b1872..f43a68b 100644 --- a/arch/arm/mach-mmp/include/mach/cputype.h +++ b/arch/arm/mach-mmp/include/mach/cputype.h @@ -4,36 +4,51 @@ #include <asm/cputype.h> /* - * CPU Stepping OLD_ID CPU_ID CHIP_ID + * CPU Stepping CPU_ID CHIP_ID * - * PXA168 A0 0x41159263 0x56158400 0x00A0A333 - * PXA910 Y0 0x41159262 0x56158000 0x00F0C910 - * MMP2 Z0 0x560f5811 + * PXA168 S0 0x56158400 0x0000C910 + * PXA168 A0 0x56158400 0x00A0A168 + * PXA910 Y1 0x56158400 0x00F2C920 + * PXA910 A0 0x56158400 0x00F2C910 + * PXA910 A1 0x56158400 0x00A0C910 + * PXA920 Y0 0x56158400 0x00F2C920 + * PXA920 A0 0x56158400 0x00A0C920 + * PXA920 A1 0x56158400 0x00A1C920 + * MMP2 Z0 0x560f5811 0x00F00410 + * MMP2 Z1 0x560f5811 0x00E00410 + * MMP2 A0 0x560f5811 0x00A0A610 */ +extern unsigned int mmp_chip_id; + #ifdef CONFIG_CPU_PXA168 -# define __cpu_is_pxa168(id) \ - ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x84; }) +static inline int cpu_is_pxa168(void) +{ + return (((read_cpuid_id() >> 8) & 0xff) == 0x84) && + ((mmp_chip_id & 0xfff) == 0x168); +} #else -# define __cpu_is_pxa168(id) (0) +#define cpu_is_pxa168() (0) #endif +/* cpu_is_pxa910() is shared on both pxa910 and pxa920 */ #ifdef CONFIG_CPU_PXA910 -# define __cpu_is_pxa910(id) \ - ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x80; }) +static inline int cpu_is_pxa910(void) +{ + return (((read_cpuid_id() >> 8) & 0xff) == 0x84) && + (((mmp_chip_id & 0xfff) == 0x910) || + ((mmp_chip_id & 0xfff) == 0x920)); +} #else -# define __cpu_is_pxa910(id) (0) +#define cpu_is_pxa910() (0) #endif #ifdef CONFIG_CPU_MMP2 -# define __cpu_is_mmp2(id) \ - ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x58; }) +static inline int cpu_is_mmp2(void) +{ + return (((cpu_readid_id() >> 8) & 0xff) == 0x58); #else -# define __cpu_is_mmp2(id) (0) +#define cpu_is_mmp2() (0) #endif -#define cpu_is_pxa168() ({ __cpu_is_pxa168(read_cpuid_id()); }) -#define cpu_is_pxa910() ({ __cpu_is_pxa910(read_cpuid_id()); }) -#define cpu_is_mmp2() ({ __cpu_is_mmp2(read_cpuid_id()); }) - #endif /* __ASM_MACH_CPUTYPE_H */ diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h index b379cde..a09d328 100644 --- a/arch/arm/mach-mmp/include/mach/irqs.h +++ b/arch/arm/mach-mmp/include/mach/irqs.h @@ -222,10 +222,8 @@ #define IRQ_GPIO_NUM 192 #define IRQ_GPIO(x) (IRQ_GPIO_START + (x)) -/* Board IRQ - 64 by default, increase if not enough */ #define IRQ_BOARD_START (IRQ_GPIO_START + IRQ_GPIO_NUM) -#define IRQ_BOARD_END (IRQ_BOARD_START + 64) -#define NR_IRQS (IRQ_BOARD_END) +#define NR_IRQS (IRQ_BOARD_START) #endif /* __ASM_MACH_IRQS_H */ diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h index ded43c4..4621067 100644 --- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h +++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h @@ -289,4 +289,11 @@ #define GPIO86_PWM1_OUT MFP_CFG(GPIO86, AF2) #define GPIO86_PWM2_OUT MFP_CFG(GPIO86, AF3) +/* Keypad */ +#define GPIO109_KP_MKIN1 MFP_CFG(GPIO109, AF7) +#define GPIO110_KP_MKIN0 MFP_CFG(GPIO110, AF7) +#define GPIO111_KP_MKOUT7 MFP_CFG(GPIO111, AF7) +#define GPIO112_KP_MKOUT6 MFP_CFG(GPIO112, AF7) +#define GPIO121_KP_MKIN4 MFP_CFG(GPIO121, AF7) + #endif /* __ASM_MACH_MFP_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 27e1bc7..1801e42 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -5,11 +5,15 @@ struct sys_timer; extern struct sys_timer pxa168_timer; extern void __init pxa168_init_irq(void); +extern void pxa168_clear_keypad_wakeup(void); #include <linux/i2c.h> #include <mach/devices.h> #include <plat/i2c.h> #include <plat/pxa3xx_nand.h> +#include <video/pxa168fb.h> +#include <plat/pxa27x_keypad.h> +#include <mach/cputype.h> extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -25,6 +29,8 @@ extern struct pxa_device_desc pxa168_device_ssp3; extern struct pxa_device_desc pxa168_device_ssp4; extern struct pxa_device_desc pxa168_device_ssp5; extern struct pxa_device_desc pxa168_device_nand; +extern struct pxa_device_desc pxa168_device_fb; +extern struct pxa_device_desc pxa168_device_keypad; static inline int pxa168_add_uart(int id) { @@ -97,4 +103,18 @@ static inline int pxa168_add_nand(struct pxa3xx_nand_platform_data *info) { return pxa_register_device(&pxa168_device_nand, info, sizeof(*info)); } + +static inline int pxa168_add_fb(struct pxa168fb_mach_info *mi) +{ + return pxa_register_device(&pxa168_device_fb, mi, sizeof(*mi)); +} + +static inline int pxa168_add_keypad(struct pxa27x_keypad_platform_data *data) +{ + if (cpu_is_pxa168()) + data->clear_wakeup_event = pxa168_clear_keypad_wakeup; + + return pxa_register_device(&pxa168_device_keypad, data, sizeof(*data)); +} + #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h index 9190305..ac47023 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h @@ -33,4 +33,16 @@ #define APMU_FNRST_DIS (1 << 1) #define APMU_AXIRST_DIS (1 << 0) +/* Wake Clear Register */ +#define APMU_WAKE_CLR APMU_REG(0x07c) + +#define APMU_PXA168_KP_WAKE_CLR (1 << 7) +#define APMU_PXA168_CFI_WAKE_CLR (1 << 6) +#define APMU_PXA168_XD_WAKE_CLR (1 << 5) +#define APMU_PXA168_MSP_WAKE_CLR (1 << 4) +#define APMU_PXA168_SD4_WAKE_CLR (1 << 3) +#define APMU_PXA168_SD3_WAKE_CLR (1 << 2) +#define APMU_PXA168_SD2_WAKE_CLR (1 << 1) +#define APMU_PXA168_SD1_WAKE_CLR (1 << 0) + #endif /* __ASM_MACH_REGS_APMU_H */ diff --git a/arch/arm/mach-mmp/include/mach/system.h b/arch/arm/mach-mmp/include/mach/system.h index 4f5b0e0..1a8a25e 100644 --- a/arch/arm/mach-mmp/include/mach/system.h +++ b/arch/arm/mach-mmp/include/mach/system.h @@ -9,6 +9,8 @@ #ifndef __ASM_MACH_SYSTEM_H #define __ASM_MACH_SYSTEM_H +#include <mach/cputype.h> + static inline void arch_idle(void) { cpu_do_idle(); @@ -16,6 +18,9 @@ static inline void arch_idle(void) static inline void arch_reset(char mode, const char *cmd) { - cpu_reset(0); + if (cpu_is_pxa168()) + cpu_reset(0xffff0000); + else + cpu_reset(0); } #endif /* __ASM_MACH_SYSTEM_H */ diff --git a/arch/arm/mach-mmp/include/mach/teton_bga.h b/arch/arm/mach-mmp/include/mach/teton_bga.h new file mode 100644 index 0000000..61a539b --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/teton_bga.h @@ -0,0 +1,27 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/teton_bga.h + * + * Support for the Marvell PXA168 Teton BGA Development Platform. + * + * 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 + * publishhed by the Free Software Foundation. + */ +#ifndef __ASM_MACH_TETON_BGA_H +#define __ASM_MACH_TETON_BGA_H + +/* GPIOs */ +#define MMC_PWENA_GPIO 27 +#define USBHPENB_GPIO 55 +#define RTC_INT_GPIO 78 +#define LCD_VBLK_EN_GPIO 79 +#define LCD_DVDD_EN_GPIO 80 +#define RST_WIFI_GPIO 81 +#define CF_PWEN_GPIO 82 +#define USB_OC_GPIO 83 +#define PWM_GPIO 84 +#define USBHPENA_GPIO 85 +#define TS_INT_GPIO 86 +#define CIR_GPIO 108 + +#endif /* __ASM_MACH_TETON_BGA_H */ diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c index 80c3e7a..940ee03 100644 --- a/arch/arm/mach-mmp/jasper.c +++ b/arch/arm/mach-mmp/jasper.c @@ -18,16 +18,18 @@ #include <linux/regulator/machine.h> #include <linux/regulator/max8649.h> #include <linux/mfd/max8925.h> +#include <linux/interrupt.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/addr-map.h> #include <mach/mfp-mmp2.h> #include <mach/mmp2.h> -#include <mach/irqs.h> #include "common.h" +#define JASPER_NR_IRQS (IRQ_BOARD_START + 48) + static unsigned long jasper_pin_config[] __initdata = { /* UART1 */ GPIO29_UART1_RXD, @@ -137,6 +139,7 @@ MACHINE_START(MARVELL_JASPER, "Jasper Development Platform") .phys_io = APB_PHYS_BASE, .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, .map_io = mmp_map_io, + .nr_irqs = JASPER_NR_IRQS, .init_irq = mmp2_init_irq, .timer = &mmp2_timer, .init_machine = jasper_init, diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 652ae66..72b4e76 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -77,8 +77,10 @@ static APBC_CLK(ssp2, PXA168_SSP2, 4, 0); static APBC_CLK(ssp3, PXA168_SSP3, 4, 0); static APBC_CLK(ssp4, PXA168_SSP4, 4, 0); static APBC_CLK(ssp5, PXA168_SSP5, 4, 0); +static APBC_CLK(keypad, PXA168_KPC, 0, 32000); static APMU_CLK(nand, NAND, 0x01db, 208000000); +static APMU_CLK(lcd, LCD, 0x7f, 312000000); /* device and clock bindings */ static struct clk_lookup pxa168_clkregs[] = { @@ -96,6 +98,8 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_ssp4, "pxa168-ssp.3", NULL), INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), + INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL), + INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL), }; static int __init pxa168_init(void) @@ -132,6 +136,16 @@ struct sys_timer pxa168_timer = { .init = pxa168_timer_init, }; +void pxa168_clear_keypad_wakeup(void) +{ + uint32_t val; + uint32_t mask = APMU_PXA168_KP_WAKE_CLR; + + /* wake event clear is needed in order to clear keypad interrupt */ + val = __raw_readl(APMU_WAKE_CLR); + __raw_writel(val | mask, APMU_WAKE_CLR); +} + /* on-chip devices */ PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22); PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24); @@ -147,3 +161,5 @@ PXA168_DEVICE(ssp2, "pxa168-ssp", 1, SSP2, 0xd401c000, 0x40, 54, 55); PXA168_DEVICE(ssp3, "pxa168-ssp", 2, SSP3, 0xd401f000, 0x40, 56, 57); PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59); PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61); +PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8); +PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c); diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c new file mode 100644 index 0000000..a4a375c --- /dev/null +++ b/arch/arm/mach-mmp/teton_bga.c @@ -0,0 +1,91 @@ +/* + * linux/arch/arm/mach-mmp/teton_bga.c + * + * Support for the Marvell PXA168 Teton BGA Development Platform. + * + * Author: Mark F. Brown <mark.brown314@gmail.com> + * + * This code is based on aspenite.c + * + * 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 + * publishhed by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/input.h> +#include <plat/pxa27x_keypad.h> +#include <linux/i2c.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <mach/addr-map.h> +#include <mach/mfp-pxa168.h> +#include <mach/pxa168.h> +#include <mach/teton_bga.h> + +#include "common.h" + +static unsigned long teton_bga_pin_config[] __initdata = { + /* UART1 */ + GPIO107_UART1_TXD, + GPIO108_UART1_RXD, + + /* Keypad */ + GPIO109_KP_MKIN1, + GPIO110_KP_MKIN0, + GPIO111_KP_MKOUT7, + GPIO112_KP_MKOUT6, + + /* I2C Bus */ + GPIO105_CI2C_SDA, + GPIO106_CI2C_SCL, + + /* RTC */ + GPIO78_GPIO, +}; + +static unsigned int teton_bga_matrix_key_map[] = { + KEY(0, 6, KEY_ESC), + KEY(0, 7, KEY_ENTER), + KEY(1, 6, KEY_LEFT), + KEY(1, 7, KEY_RIGHT), +}; + +static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = { + .matrix_key_rows = 2, + .matrix_key_cols = 8, + .matrix_key_map = teton_bga_matrix_key_map, + .matrix_key_map_size = ARRAY_SIZE(teton_bga_matrix_key_map), + .debounce_interval = 30, +}; + +static struct i2c_board_info teton_bga_i2c_info[] __initdata = { + { + I2C_BOARD_INFO("ds1337", 0x68), + .irq = gpio_to_irq(RTC_INT_GPIO) + }, +}; + +static void __init teton_bga_init(void) +{ + mfp_config(ARRAY_AND_SIZE(teton_bga_pin_config)); + + /* on-chip devices */ + pxa168_add_uart(1); + pxa168_add_keypad(&teton_bga_keypad_info); + pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(teton_bga_i2c_info)); +} + +MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform") + .phys_io = APB_PHYS_BASE, + .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, + .map_io = mmp_map_io, + .nr_irqs = IRQ_BOARD_START, + .init_irq = pxa168_init_irq, + .timer = &pxa168_timer, + .init_machine = teton_bga_init, +MACHINE_END diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c index ee65e05..5457113 100644 --- a/arch/arm/mach-mmp/ttc_dkb.c +++ b/arch/arm/mach-mmp/ttc_dkb.c @@ -14,6 +14,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/onenand.h> +#include <linux/interrupt.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -24,6 +25,8 @@ #include "common.h" +#define TTCDKB_NR_IRQS (IRQ_BOARD_START + 24) + static unsigned long ttc_dkb_pin_config[] __initdata = { /* UART2 */ GPIO47_UART2_RXD, @@ -125,6 +128,7 @@ MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform") .phys_io = APB_PHYS_BASE, .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc, .map_io = mmp_map_io, + .nr_irqs = TTCDKB_NR_IRQS, .init_irq = pxa910_init_irq, .timer = &pxa910_timer, .init_machine = ttc_dkb_init, diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 47264a7..3115a29 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -10,6 +10,8 @@ config ARCH_MSM7X00A select MSM_SMD select MSM_SMD_PKG3 select CPU_V6 + select MSM_PROC_COMM + select HAS_MSM_DEBUG_UART_PHYS config ARCH_MSM7X30 bool "MSM7x30" @@ -18,6 +20,9 @@ config ARCH_MSM7X30 select MSM_VIC select CPU_V7 select MSM_REMOTE_SPINLOCK_DEKKERS + select MSM_GPIOMUX + select MSM_PROC_COMM + select HAS_MSM_DEBUG_UART_PHYS config ARCH_QSD8X50 bool "QSD8X50" @@ -26,6 +31,19 @@ config ARCH_QSD8X50 select MSM_VIC select CPU_V7 select MSM_REMOTE_SPINLOCK_LDREX + select MSM_GPIOMUX + select MSM_PROC_COMM + select HAS_MSM_DEBUG_UART_PHYS + +config ARCH_MSM8X60 + bool "MSM8X60" + select ARM_GIC + select CPU_V7 + select MSM_V2_TLMM + select MSM_GPIOMUX + select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \ + && !MACH_MSM8X60_FFA) + endchoice config MSM_SOC_REV_A @@ -36,6 +54,9 @@ config ARCH_MSM_ARM11 config ARCH_MSM_SCORPION bool +config HAS_MSM_DEBUG_UART_PHYS + bool + config MSM_VIC bool @@ -74,6 +95,30 @@ config MACH_QSD8X50A_ST1_5 help Support for the Qualcomm ST1.5. +config MACH_MSM8X60_RUMI3 + depends on ARCH_MSM8X60 + bool "MSM8x60 RUMI3" + help + Support for the Qualcomm MSM8x60 RUMI3 emulator. + +config MACH_MSM8X60_SURF + depends on ARCH_MSM8X60 + bool "MSM8x60 SURF" + help + Support for the Qualcomm MSM8x60 SURF eval board. + +config MACH_MSM8X60_SIM + depends on ARCH_MSM8X60 + bool "MSM8x60 Simulator" + help + Support for the Qualcomm MSM8x60 simulator. + +config MACH_MSM8X60_FFA + depends on ARCH_MSM8X60 + bool "MSM8x60 FFA" + help + Support for the Qualcomm MSM8x60 FFA eval board. + endmenu config MSM_DEBUG_UART @@ -82,6 +127,7 @@ config MSM_DEBUG_UART default 2 if MSM_DEBUG_UART2 default 3 if MSM_DEBUG_UART3 +if HAS_MSM_DEBUG_UART_PHYS choice prompt "Debug UART" @@ -99,11 +145,20 @@ choice config MSM_DEBUG_UART3 bool "UART3" endchoice +endif config MSM_SMD_PKG3 bool +config MSM_PROC_COMM + bool + config MSM_SMD bool +config MSM_GPIOMUX + bool + +config MSM_V2_TLMM + bool endif diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 7046106..b5a7b07 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -1,16 +1,20 @@ -obj-y += proc_comm.o -obj-y += io.o idle.o timer.o dma.o -obj-y += vreg.o +obj-y += io.o idle.o timer.o +ifndef CONFIG_ARCH_MSM8X60 obj-y += acpuclock-arm11.o -obj-y += clock.o clock-pcom.o -obj-y += gpio.o +obj-y += dma.o +endif ifdef CONFIG_MSM_VIC obj-y += irq-vic.o else +ifndef CONFIG_ARCH_MSM8X60 obj-y += irq.o endif +endif +obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o devices-msm8x60-iommu.o +obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o +obj-$(CONFIG_MSM_PROC_COMM) += clock.o obj-$(CONFIG_ARCH_QSD8X50) += sirc.o obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o obj-$(CONFIG_MSM_SMD) += last_radio_log.o @@ -19,4 +23,11 @@ obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o d obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o +obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o +obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o +obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o +obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o +ifndef CONFIG_MSM_V2_TLMM +obj-y += gpio.o +endif diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index e329819..76d5a22 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -39,27 +39,11 @@ extern struct sys_timer msm_timer; -#ifdef CONFIG_SERIAL_MSM_CONSOLE -static struct msm_gpio uart2_config_data[] = { - { GPIO_CFG(49, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_RFR"}, - { GPIO_CFG(50, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_CTS"}, - { GPIO_CFG(51, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"}, - { GPIO_CFG(52, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"}, -}; - -static void msm7x30_init_uart2(void) -{ - msm_gpios_request_enable(uart2_config_data, - ARRAY_SIZE(uart2_config_data)); - -} -#endif - static struct platform_device *devices[] __initdata = { #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER) &msm_device_uart2, #endif - + &msm_device_smd, }; static void __init msm7x30_init_irq(void) @@ -70,10 +54,6 @@ static void __init msm7x30_init_irq(void) static void __init msm7x30_init(void) { platform_add_devices(devices, ARRAY_SIZE(devices)); -#ifdef CONFIG_SERIAL_MSM_CONSOLE - msm7x30_init_uart2(); -#endif - } static void __init msm7x30_map_io(void) diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c new file mode 100644 index 0000000..7486a68 --- /dev/null +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -0,0 +1,100 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/irq.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/hardware/gic.h> + +#include <mach/board.h> +#include <mach/msm_iomap.h> + +void __iomem *gic_cpu_base_addr; + +unsigned long clk_get_max_axi_khz(void) +{ + return 0; +} + +static void __init msm8x60_map_io(void) +{ + msm_map_msm8x60_io(); +} + +static void __init msm8x60_init_irq(void) +{ + unsigned int i; + + gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START); + gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE; + gic_cpu_init(0, MSM_QGIC_CPU_BASE); + + /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */ + writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4); + + /* RUMI does not adhere to GIC spec by enabling STIs by default. + * Enable/clear is supposed to be RO for STIs, but is RW on RUMI. + */ + if (!machine_is_msm8x60_sim()) + writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET); + + /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet + * as they are configured as level, which does not play nice with + * handle_percpu_irq. + */ + for (i = GIC_PPI_START; i < GIC_SPI_START; i++) { + if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE) + set_irq_handler(i, handle_percpu_irq); + } +} + +static void __init msm8x60_init(void) +{ +} + +MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3") + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF") + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR") + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA") + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index e3cc807..d5d5e44 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -35,20 +35,49 @@ extern struct sys_timer msm_timer; -static struct msm_gpio uart3_config_data[] = { - { GPIO_CFG(86, 1, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"}, - { GPIO_CFG(87, 1, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"}, +static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300; +static const unsigned qsd8x50_surf_smc91x_gpio __initdata = 156; + +/* Leave smc91x resources empty here, as we'll fill them in + * at run-time: they vary from board to board, and the true + * configuration won't be known until boot. + */ +static struct resource smc91x_resources[] __initdata = { + [0] = { + .flags = IORESOURCE_MEM, + }, + [1] = { + .flags = IORESOURCE_IRQ, + }, }; -static struct platform_device *devices[] __initdata = { - &msm_device_uart3, +static struct platform_device smc91x_device __initdata = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, }; -static void msm8x50_init_uart3(void) +static int __init msm_init_smc91x(void) { - msm_gpios_request_enable(uart3_config_data, - ARRAY_SIZE(uart3_config_data)); + if (machine_is_qsd8x50_surf()) { + smc91x_resources[0].start = qsd8x50_surf_smc91x_base; + smc91x_resources[0].end = qsd8x50_surf_smc91x_base + 0xff; + smc91x_resources[1].start = + gpio_to_irq(qsd8x50_surf_smc91x_gpio); + smc91x_resources[1].end = + gpio_to_irq(qsd8x50_surf_smc91x_gpio); + platform_device_register(&smc91x_device); + } + + return 0; } +module_init(msm_init_smc91x); + +static struct platform_device *devices[] __initdata = { + &msm_device_uart3, + &msm_device_smd, +}; static void __init qsd8x50_map_io(void) { @@ -64,7 +93,6 @@ static void __init qsd8x50_init_irq(void) static void __init qsd8x50_init(void) { - msm8x50_init_uart3(); platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c new file mode 100644 index 0000000..1250d22 --- /dev/null +++ b/arch/arm/mach-msm/clock-dummy.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/module.h> + +struct clk *clk_get(struct device *dev, const char *id) +{ + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +int clk_enable(struct clk *clk) +{ + return -ENOENT; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_get_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return -ENOENT; +} +EXPORT_SYMBOL(clk_set_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c index b449e8a..7fcf2e3 100644 --- a/arch/arm/mach-msm/devices-msm7x30.c +++ b/arch/arm/mach-msm/devices-msm7x30.c @@ -51,6 +51,11 @@ struct platform_device msm_device_uart2 = { .resource = resources_uart2, }; +struct platform_device msm_device_smd = { + .name = "msm_smd", + .id = -1, +}; + struct clk msm_clocks_7x30[] = { CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), diff --git a/arch/arm/mach-msm/devices-msm8x60-iommu.c b/arch/arm/mach-msm/devices-msm8x60-iommu.c new file mode 100644 index 0000000..89b9d44 --- /dev/null +++ b/arch/arm/mach-msm/devices-msm8x60-iommu.c @@ -0,0 +1,883 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/bootmem.h> + +#include <mach/msm_iomap-8x60.h> +#include <mach/irqs-8x60.h> +#include <mach/iommu.h> + +static struct resource msm_iommu_jpegd_resources[] = { + { + .start = MSM_IOMMU_JPEGD_PHYS, + .end = MSM_IOMMU_JPEGD_PHYS + MSM_IOMMU_JPEGD_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ, + .end = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_JPEGD_CB_SC_SECURE_IRQ, + .end = SMMU_JPEGD_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vpe_resources[] = { + { + .start = MSM_IOMMU_VPE_PHYS, + .end = MSM_IOMMU_VPE_PHYS + MSM_IOMMU_VPE_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VPE_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VPE_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VPE_CB_SC_SECURE_IRQ, + .end = SMMU_VPE_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_mdp0_resources[] = { + { + .start = MSM_IOMMU_MDP0_PHYS, + .end = MSM_IOMMU_MDP0_PHYS + MSM_IOMMU_MDP0_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ, + .end = SMMU_MDP0_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_MDP0_CB_SC_SECURE_IRQ, + .end = SMMU_MDP0_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_mdp1_resources[] = { + { + .start = MSM_IOMMU_MDP1_PHYS, + .end = MSM_IOMMU_MDP1_PHYS + MSM_IOMMU_MDP1_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ, + .end = SMMU_MDP1_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_MDP1_CB_SC_SECURE_IRQ, + .end = SMMU_MDP1_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_rot_resources[] = { + { + .start = MSM_IOMMU_ROT_PHYS, + .end = MSM_IOMMU_ROT_PHYS + MSM_IOMMU_ROT_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_ROT_CB_SC_NON_SECURE_IRQ, + .end = SMMU_ROT_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_ROT_CB_SC_SECURE_IRQ, + .end = SMMU_ROT_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_ijpeg_resources[] = { + { + .start = MSM_IOMMU_IJPEG_PHYS, + .end = MSM_IOMMU_IJPEG_PHYS + MSM_IOMMU_IJPEG_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ, + .end = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_IJPEG_CB_SC_SECURE_IRQ, + .end = SMMU_IJPEG_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vfe_resources[] = { + { + .start = MSM_IOMMU_VFE_PHYS, + .end = MSM_IOMMU_VFE_PHYS + MSM_IOMMU_VFE_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VFE_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VFE_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VFE_CB_SC_SECURE_IRQ, + .end = SMMU_VFE_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vcodec_a_resources[] = { + { + .start = MSM_IOMMU_VCODEC_A_PHYS, + .end = MSM_IOMMU_VCODEC_A_PHYS + MSM_IOMMU_VCODEC_A_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ, + .end = SMMU_VCODEC_A_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vcodec_b_resources[] = { + { + .start = MSM_IOMMU_VCODEC_B_PHYS, + .end = MSM_IOMMU_VCODEC_B_PHYS + MSM_IOMMU_VCODEC_B_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ, + .end = SMMU_VCODEC_B_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_gfx3d_resources[] = { + { + .start = MSM_IOMMU_GFX3D_PHYS, + .end = MSM_IOMMU_GFX3D_PHYS + MSM_IOMMU_GFX3D_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ, + .end = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_GFX3D_CB_SC_SECURE_IRQ, + .end = SMMU_GFX3D_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_gfx2d0_resources[] = { + { + .start = MSM_IOMMU_GFX2D0_PHYS, + .end = MSM_IOMMU_GFX2D0_PHYS + MSM_IOMMU_GFX2D0_SIZE - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ, + .end = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_GFX2D0_CB_SC_SECURE_IRQ, + .end = SMMU_GFX2D0_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device msm_root_iommu_dev = { + .name = "msm_iommu", + .id = -1, +}; + +static struct msm_iommu_dev jpegd_smmu = { + .name = "jpegd", + .clk_rate = -1 +}; + +static struct msm_iommu_dev vpe_smmu = { + .name = "vpe" +}; + +static struct msm_iommu_dev mdp0_smmu = { + .name = "mdp0" +}; + +static struct msm_iommu_dev mdp1_smmu = { + .name = "mdp1" +}; + +static struct msm_iommu_dev rot_smmu = { + .name = "rot" +}; + +static struct msm_iommu_dev ijpeg_smmu = { + .name = "ijpeg" +}; + +static struct msm_iommu_dev vfe_smmu = { + .name = "vfe", + .clk_rate = -1 +}; + +static struct msm_iommu_dev vcodec_a_smmu = { + .name = "vcodec_a" +}; + +static struct msm_iommu_dev vcodec_b_smmu = { + .name = "vcodec_b" +}; + +static struct msm_iommu_dev gfx3d_smmu = { + .name = "gfx3d", + .clk_rate = 27000000 +}; + +static struct msm_iommu_dev gfx2d0_smmu = { + .name = "gfx2d0", + .clk_rate = 27000000 +}; + +static struct platform_device msm_device_smmu_jpegd = { + .name = "msm_iommu", + .id = 0, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources), + .resource = msm_iommu_jpegd_resources, +}; + +static struct platform_device msm_device_smmu_vpe = { + .name = "msm_iommu", + .id = 1, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vpe_resources), + .resource = msm_iommu_vpe_resources, +}; + +static struct platform_device msm_device_smmu_mdp0 = { + .name = "msm_iommu", + .id = 2, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources), + .resource = msm_iommu_mdp0_resources, +}; + +static struct platform_device msm_device_smmu_mdp1 = { + .name = "msm_iommu", + .id = 3, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources), + .resource = msm_iommu_mdp1_resources, +}; + +static struct platform_device msm_device_smmu_rot = { + .name = "msm_iommu", + .id = 4, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_rot_resources), + .resource = msm_iommu_rot_resources, +}; + +static struct platform_device msm_device_smmu_ijpeg = { + .name = "msm_iommu", + .id = 5, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources), + .resource = msm_iommu_ijpeg_resources, +}; + +static struct platform_device msm_device_smmu_vfe = { + .name = "msm_iommu", + .id = 6, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vfe_resources), + .resource = msm_iommu_vfe_resources, +}; + +static struct platform_device msm_device_smmu_vcodec_a = { + .name = "msm_iommu", + .id = 7, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources), + .resource = msm_iommu_vcodec_a_resources, +}; + +static struct platform_device msm_device_smmu_vcodec_b = { + .name = "msm_iommu", + .id = 8, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources), + .resource = msm_iommu_vcodec_b_resources, +}; + +static struct platform_device msm_device_smmu_gfx3d = { + .name = "msm_iommu", + .id = 9, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources), + .resource = msm_iommu_gfx3d_resources, +}; + +static struct platform_device msm_device_smmu_gfx2d0 = { + .name = "msm_iommu", + .id = 10, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources), + .resource = msm_iommu_gfx2d0_resources, +}; + +static struct msm_iommu_ctx_dev jpegd_src_ctx = { + .name = "jpegd_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev jpegd_dst_ctx = { + .name = "jpegd_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev vpe_src_ctx = { + .name = "vpe_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev vpe_dst_ctx = { + .name = "vpe_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev mdp_vg1_ctx = { + .name = "mdp_vg1", + .num = 0, + .mids = {0, 2, -1} +}; + +static struct msm_iommu_ctx_dev mdp_rgb1_ctx = { + .name = "mdp_rgb1", + .num = 1, + .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1} +}; + +static struct msm_iommu_ctx_dev mdp_vg2_ctx = { + .name = "mdp_vg2", + .num = 0, + .mids = {0, 2, -1} +}; + +static struct msm_iommu_ctx_dev mdp_rgb2_ctx = { + .name = "mdp_rgb2", + .num = 1, + .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1} +}; + +static struct msm_iommu_ctx_dev rot_src_ctx = { + .name = "rot_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev rot_dst_ctx = { + .name = "rot_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev ijpeg_src_ctx = { + .name = "ijpeg_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev ijpeg_dst_ctx = { + .name = "ijpeg_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev vfe_imgwr_ctx = { + .name = "vfe_imgwr", + .num = 0, + .mids = {2, 3, 4, 5, 6, 7, 8, -1} +}; + +static struct msm_iommu_ctx_dev vfe_misc_ctx = { + .name = "vfe_misc", + .num = 1, + .mids = {0, 1, 9, -1} +}; + +static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = { + .name = "vcodec_a_stream", + .num = 0, + .mids = {2, 5, -1} +}; + +static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = { + .name = "vcodec_a_mm1", + .num = 1, + .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1} +}; + +static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = { + .name = "vcodec_b_mm2", + .num = 0, + .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1} +}; + +static struct msm_iommu_ctx_dev gfx3d_rbpa_ctx = { + .name = "gfx3d_rbpa", + .num = 0, + .mids = {-1} +}; + +static struct msm_iommu_ctx_dev gfx3d_cpvgttc_ctx = { + .name = "gfx3d_cpvgttc", + .num = 1, + .mids = {0, 1, 2, 3, 4, 5, 6, 7, -1} +}; + +static struct msm_iommu_ctx_dev gfx3d_smmu_ctx = { + .name = "gfx3d_smmu", + .num = 2, + .mids = {8, 9, 10, 11, 12, -1} +}; + +static struct msm_iommu_ctx_dev gfx2d0_pixv1_ctx = { + .name = "gfx2d0_pixv1_smmu", + .num = 0, + .mids = {0, 3, 4, -1} +}; + +static struct msm_iommu_ctx_dev gfx2d0_texv3_ctx = { + .name = "gfx2d0_texv3_smmu", + .num = 1, + .mids = {1, 6, 7, -1} +}; + +static struct platform_device msm_device_jpegd_src_ctx = { + .name = "msm_iommu_ctx", + .id = 0, + .dev = { + .parent = &msm_device_smmu_jpegd.dev, + }, +}; + +static struct platform_device msm_device_jpegd_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 1, + .dev = { + .parent = &msm_device_smmu_jpegd.dev, + }, +}; + +static struct platform_device msm_device_vpe_src_ctx = { + .name = "msm_iommu_ctx", + .id = 2, + .dev = { + .parent = &msm_device_smmu_vpe.dev, + }, +}; + +static struct platform_device msm_device_vpe_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 3, + .dev = { + .parent = &msm_device_smmu_vpe.dev, + }, +}; + +static struct platform_device msm_device_mdp_vg1_ctx = { + .name = "msm_iommu_ctx", + .id = 4, + .dev = { + .parent = &msm_device_smmu_mdp0.dev, + }, +}; + +static struct platform_device msm_device_mdp_rgb1_ctx = { + .name = "msm_iommu_ctx", + .id = 5, + .dev = { + .parent = &msm_device_smmu_mdp0.dev, + }, +}; + +static struct platform_device msm_device_mdp_vg2_ctx = { + .name = "msm_iommu_ctx", + .id = 6, + .dev = { + .parent = &msm_device_smmu_mdp1.dev, + }, +}; + +static struct platform_device msm_device_mdp_rgb2_ctx = { + .name = "msm_iommu_ctx", + .id = 7, + .dev = { + .parent = &msm_device_smmu_mdp1.dev, + }, +}; + +static struct platform_device msm_device_rot_src_ctx = { + .name = "msm_iommu_ctx", + .id = 8, + .dev = { + .parent = &msm_device_smmu_rot.dev, + }, +}; + +static struct platform_device msm_device_rot_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 9, + .dev = { + .parent = &msm_device_smmu_rot.dev, + }, +}; + +static struct platform_device msm_device_ijpeg_src_ctx = { + .name = "msm_iommu_ctx", + .id = 10, + .dev = { + .parent = &msm_device_smmu_ijpeg.dev, + }, +}; + +static struct platform_device msm_device_ijpeg_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 11, + .dev = { + .parent = &msm_device_smmu_ijpeg.dev, + }, +}; + +static struct platform_device msm_device_vfe_imgwr_ctx = { + .name = "msm_iommu_ctx", + .id = 12, + .dev = { + .parent = &msm_device_smmu_vfe.dev, + }, +}; + +static struct platform_device msm_device_vfe_misc_ctx = { + .name = "msm_iommu_ctx", + .id = 13, + .dev = { + .parent = &msm_device_smmu_vfe.dev, + }, +}; + +static struct platform_device msm_device_vcodec_a_stream_ctx = { + .name = "msm_iommu_ctx", + .id = 14, + .dev = { + .parent = &msm_device_smmu_vcodec_a.dev, + }, +}; + +static struct platform_device msm_device_vcodec_a_mm1_ctx = { + .name = "msm_iommu_ctx", + .id = 15, + .dev = { + .parent = &msm_device_smmu_vcodec_a.dev, + }, +}; + +static struct platform_device msm_device_vcodec_b_mm2_ctx = { + .name = "msm_iommu_ctx", + .id = 16, + .dev = { + .parent = &msm_device_smmu_vcodec_b.dev, + }, +}; + +static struct platform_device msm_device_gfx3d_rbpa_ctx = { + .name = "msm_iommu_ctx", + .id = 17, + .dev = { + .parent = &msm_device_smmu_gfx3d.dev, + }, +}; + +static struct platform_device msm_device_gfx3d_cpvgttc_ctx = { + .name = "msm_iommu_ctx", + .id = 18, + .dev = { + .parent = &msm_device_smmu_gfx3d.dev, + }, +}; + +static struct platform_device msm_device_gfx3d_smmu_ctx = { + .name = "msm_iommu_ctx", + .id = 19, + .dev = { + .parent = &msm_device_smmu_gfx3d.dev, + }, +}; + +static struct platform_device msm_device_gfx2d0_pixv1_ctx = { + .name = "msm_iommu_ctx", + .id = 20, + .dev = { + .parent = &msm_device_smmu_gfx2d0.dev, + }, +}; + +static struct platform_device msm_device_gfx2d0_texv3_ctx = { + .name = "msm_iommu_ctx", + .id = 21, + .dev = { + .parent = &msm_device_smmu_gfx2d0.dev, + }, +}; + +static struct platform_device *msm_iommu_devs[] = { + &msm_device_smmu_jpegd, + &msm_device_smmu_vpe, + &msm_device_smmu_mdp0, + &msm_device_smmu_mdp1, + &msm_device_smmu_rot, + &msm_device_smmu_ijpeg, + &msm_device_smmu_vfe, + &msm_device_smmu_vcodec_a, + &msm_device_smmu_vcodec_b, + &msm_device_smmu_gfx3d, + &msm_device_smmu_gfx2d0, +}; + +static struct msm_iommu_dev *msm_iommu_data[] = { + &jpegd_smmu, + &vpe_smmu, + &mdp0_smmu, + &mdp1_smmu, + &rot_smmu, + &ijpeg_smmu, + &vfe_smmu, + &vcodec_a_smmu, + &vcodec_b_smmu, + &gfx3d_smmu, + &gfx2d0_smmu, +}; + +static struct platform_device *msm_iommu_ctx_devs[] = { + &msm_device_jpegd_src_ctx, + &msm_device_jpegd_dst_ctx, + &msm_device_vpe_src_ctx, + &msm_device_vpe_dst_ctx, + &msm_device_mdp_vg1_ctx, + &msm_device_mdp_rgb1_ctx, + &msm_device_mdp_vg2_ctx, + &msm_device_mdp_rgb2_ctx, + &msm_device_rot_src_ctx, + &msm_device_rot_dst_ctx, + &msm_device_ijpeg_src_ctx, + &msm_device_ijpeg_dst_ctx, + &msm_device_vfe_imgwr_ctx, + &msm_device_vfe_misc_ctx, + &msm_device_vcodec_a_stream_ctx, + &msm_device_vcodec_a_mm1_ctx, + &msm_device_vcodec_b_mm2_ctx, + &msm_device_gfx3d_rbpa_ctx, + &msm_device_gfx3d_cpvgttc_ctx, + &msm_device_gfx3d_smmu_ctx, + &msm_device_gfx2d0_pixv1_ctx, + &msm_device_gfx2d0_texv3_ctx, +}; + +static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = { + &jpegd_src_ctx, + &jpegd_dst_ctx, + &vpe_src_ctx, + &vpe_dst_ctx, + &mdp_vg1_ctx, + &mdp_rgb1_ctx, + &mdp_vg2_ctx, + &mdp_rgb2_ctx, + &rot_src_ctx, + &rot_dst_ctx, + &ijpeg_src_ctx, + &ijpeg_dst_ctx, + &vfe_imgwr_ctx, + &vfe_misc_ctx, + &vcodec_a_stream_ctx, + &vcodec_a_mm1_ctx, + &vcodec_b_mm2_ctx, + &gfx3d_rbpa_ctx, + &gfx3d_cpvgttc_ctx, + &gfx3d_smmu_ctx, + &gfx2d0_pixv1_ctx, + &gfx2d0_texv3_ctx, +}; + +static int msm8x60_iommu_init(void) +{ + int ret, i; + + ret = platform_device_register(&msm_root_iommu_dev); + if (ret != 0) { + pr_err("Failed to register root IOMMU device!\n"); + goto failure; + } + + for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) { + ret = platform_device_add_data(msm_iommu_devs[i], + msm_iommu_data[i], + sizeof(struct msm_iommu_dev)); + if (ret != 0) { + pr_err("platform_device_add_data failed, " + "i = %d\n", i); + goto failure_unwind; + } + + ret = platform_device_register(msm_iommu_devs[i]); + + if (ret != 0) { + pr_err("platform_device_register smmu failed, " + "i = %d\n", i); + goto failure_unwind; + } + } + + for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) { + ret = platform_device_add_data(msm_iommu_ctx_devs[i], + msm_iommu_ctx_data[i], + sizeof(*msm_iommu_ctx_devs[i])); + if (ret != 0) { + pr_err("platform_device_add_data smmu failed, " + "i = %d\n", i); + goto failure_unwind2; + } + + ret = platform_device_register(msm_iommu_ctx_devs[i]); + if (ret != 0) { + pr_err("platform_device_register ctx failed, " + "i = %d\n", i); + goto failure_unwind2; + } + } + return 0; + +failure_unwind2: + while (--i >= 0) + platform_device_unregister(msm_iommu_ctx_devs[i]); +failure_unwind: + while (--i >= 0) + platform_device_unregister(msm_iommu_devs[i]); + + platform_device_unregister(&msm_root_iommu_dev); +failure: + return ret; +} + +static void msm8x60_iommu_exit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) + platform_device_unregister(msm_iommu_ctx_devs[i]); + + for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i) + platform_device_unregister(msm_iommu_devs[i]); + + platform_device_unregister(&msm_root_iommu_dev); +} + +subsys_initcall(msm8x60_iommu_init); +module_exit(msm8x60_iommu_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c index 4d4a507..6fe67c5 100644 --- a/arch/arm/mach-msm/devices-qsd8x50.c +++ b/arch/arm/mach-msm/devices-qsd8x50.c @@ -48,6 +48,11 @@ struct platform_device msm_device_uart3 = { .resource = resources_uart3, }; +struct platform_device msm_device_smd = { + .name = "msm_smd", + .id = -1, +}; + struct clk msm_clocks_8x50[] = { CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), diff --git a/arch/arm/mach-msm/gpio.c b/arch/arm/mach-msm/gpio.c index bc32c84..33051b5 100644 --- a/arch/arm/mach-msm/gpio.c +++ b/arch/arm/mach-msm/gpio.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-msm/gpio.c * * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -14,72 +14,363 @@ * */ +#include <linux/bitops.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/irq.h> #include <linux/module.h> -#include <mach/gpio.h> -#include "proc_comm.h" - -int gpio_tlmm_config(unsigned config, unsigned disable) -{ - return msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, &disable); -} -EXPORT_SYMBOL(gpio_tlmm_config); - -int msm_gpios_enable(const struct msm_gpio *table, int size) -{ - int rc; - int i; - const struct msm_gpio *g; - for (i = 0; i < size; i++) { - g = table + i; - rc = gpio_tlmm_config(g->gpio_cfg, GPIO_ENABLE); - if (rc) { - pr_err("gpio_tlmm_config(0x%08x, GPIO_ENABLE)" - " <%s> failed: %d\n", - g->gpio_cfg, g->label ?: "?", rc); - pr_err("pin %d func %d dir %d pull %d drvstr %d\n", - GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg), - GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg), - GPIO_DRVSTR(g->gpio_cfg)); - goto err; - } +#include "gpio_hw.h" +#include "gpiomux.h" + +#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0) + +#define MSM_GPIO_BANK(bank, first, last) \ + { \ + .regs = { \ + .out = MSM_GPIO_OUT_##bank, \ + .in = MSM_GPIO_IN_##bank, \ + .int_status = MSM_GPIO_INT_STATUS_##bank, \ + .int_clear = MSM_GPIO_INT_CLEAR_##bank, \ + .int_en = MSM_GPIO_INT_EN_##bank, \ + .int_edge = MSM_GPIO_INT_EDGE_##bank, \ + .int_pos = MSM_GPIO_INT_POS_##bank, \ + .oe = MSM_GPIO_OE_##bank, \ + }, \ + .chip = { \ + .base = (first), \ + .ngpio = (last) - (first) + 1, \ + .get = msm_gpio_get, \ + .set = msm_gpio_set, \ + .direction_input = msm_gpio_direction_input, \ + .direction_output = msm_gpio_direction_output, \ + .to_irq = msm_gpio_to_irq, \ + .request = msm_gpio_request, \ + .free = msm_gpio_free, \ + } \ } + +#define MSM_GPIO_BROKEN_INT_CLEAR 1 + +struct msm_gpio_regs { + void __iomem *out; + void __iomem *in; + void __iomem *int_status; + void __iomem *int_clear; + void __iomem *int_en; + void __iomem *int_edge; + void __iomem *int_pos; + void __iomem *oe; +}; + +struct msm_gpio_chip { + spinlock_t lock; + struct gpio_chip chip; + struct msm_gpio_regs regs; +#if MSM_GPIO_BROKEN_INT_CLEAR + unsigned int_status_copy; +#endif + unsigned int both_edge_detect; + unsigned int int_enable[2]; /* 0: awake, 1: sleep */ +}; + +static int msm_gpio_write(struct msm_gpio_chip *msm_chip, + unsigned offset, unsigned on) +{ + unsigned mask = BIT(offset); + unsigned val; + + val = readl(msm_chip->regs.out); + if (on) + writel(val | mask, msm_chip->regs.out); + else + writel(val & ~mask, msm_chip->regs.out); return 0; -err: - msm_gpios_disable(table, i); - return rc; -} -EXPORT_SYMBOL(msm_gpios_enable); - -void msm_gpios_disable(const struct msm_gpio *table, int size) -{ - int rc; - int i; - const struct msm_gpio *g; - for (i = size-1; i >= 0; i--) { - g = table + i; - rc = gpio_tlmm_config(g->gpio_cfg, GPIO_DISABLE); - if (rc) { - pr_err("gpio_tlmm_config(0x%08x, GPIO_DISABLE)" - " <%s> failed: %d\n", - g->gpio_cfg, g->label ?: "?", rc); - pr_err("pin %d func %d dir %d pull %d drvstr %d\n", - GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg), - GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg), - GPIO_DRVSTR(g->gpio_cfg)); - } +} + +static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip) +{ + int loop_limit = 100; + unsigned pol, val, val2, intstat; + do { + val = readl(msm_chip->regs.in); + pol = readl(msm_chip->regs.int_pos); + pol = (pol & ~msm_chip->both_edge_detect) | + (~val & msm_chip->both_edge_detect); + writel(pol, msm_chip->regs.int_pos); + intstat = readl(msm_chip->regs.int_status); + val2 = readl(msm_chip->regs.in); + if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0) + return; + } while (loop_limit-- > 0); + printk(KERN_ERR "msm_gpio_update_both_edge_detect, " + "failed to reach stable state %x != %x\n", val, val2); +} + +static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip, + unsigned offset) +{ + unsigned bit = BIT(offset); + +#if MSM_GPIO_BROKEN_INT_CLEAR + /* Save interrupts that already triggered before we loose them. */ + /* Any interrupt that triggers between the read of int_status */ + /* and the write to int_clear will still be lost though. */ + msm_chip->int_status_copy |= readl(msm_chip->regs.int_status); + msm_chip->int_status_copy &= ~bit; +#endif + writel(bit, msm_chip->regs.int_clear); + msm_gpio_update_both_edge_detect(msm_chip); + return 0; +} + +static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct msm_gpio_chip *msm_chip; + unsigned long irq_flags; + + msm_chip = container_of(chip, struct msm_gpio_chip, chip); + spin_lock_irqsave(&msm_chip->lock, irq_flags); + writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe); + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); + return 0; +} + +static int +msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) +{ + struct msm_gpio_chip *msm_chip; + unsigned long irq_flags; + + msm_chip = container_of(chip, struct msm_gpio_chip, chip); + spin_lock_irqsave(&msm_chip->lock, irq_flags); + msm_gpio_write(msm_chip, offset, value); + writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe); + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); + return 0; +} + +static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct msm_gpio_chip *msm_chip; + + msm_chip = container_of(chip, struct msm_gpio_chip, chip); + return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0; +} + +static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct msm_gpio_chip *msm_chip; + unsigned long irq_flags; + + msm_chip = container_of(chip, struct msm_gpio_chip, chip); + spin_lock_irqsave(&msm_chip->lock, irq_flags); + msm_gpio_write(msm_chip, offset, value); + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); +} + +static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + return MSM_GPIO_TO_INT(chip->base + offset); +} + +#ifdef CONFIG_MSM_GPIOMUX +static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return msm_gpiomux_get(chip->base + offset); +} + +static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + msm_gpiomux_put(chip->base + offset); +} +#else +#define msm_gpio_request NULL +#define msm_gpio_free NULL +#endif + +struct msm_gpio_chip msm_gpio_chips[] = { +#if defined(CONFIG_ARCH_MSM7X00A) + MSM_GPIO_BANK(0, 0, 15), + MSM_GPIO_BANK(1, 16, 42), + MSM_GPIO_BANK(2, 43, 67), + MSM_GPIO_BANK(3, 68, 94), + MSM_GPIO_BANK(4, 95, 106), + MSM_GPIO_BANK(5, 107, 121), +#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27) + MSM_GPIO_BANK(0, 0, 15), + MSM_GPIO_BANK(1, 16, 42), + MSM_GPIO_BANK(2, 43, 67), + MSM_GPIO_BANK(3, 68, 94), + MSM_GPIO_BANK(4, 95, 106), + MSM_GPIO_BANK(5, 107, 132), +#elif defined(CONFIG_ARCH_MSM7X30) + MSM_GPIO_BANK(0, 0, 15), + MSM_GPIO_BANK(1, 16, 43), + MSM_GPIO_BANK(2, 44, 67), + MSM_GPIO_BANK(3, 68, 94), + MSM_GPIO_BANK(4, 95, 106), + MSM_GPIO_BANK(5, 107, 133), + MSM_GPIO_BANK(6, 134, 150), + MSM_GPIO_BANK(7, 151, 181), +#elif defined(CONFIG_ARCH_QSD8X50) + MSM_GPIO_BANK(0, 0, 15), + MSM_GPIO_BANK(1, 16, 42), + MSM_GPIO_BANK(2, 43, 67), + MSM_GPIO_BANK(3, 68, 94), + MSM_GPIO_BANK(4, 95, 103), + MSM_GPIO_BANK(5, 104, 121), + MSM_GPIO_BANK(6, 122, 152), + MSM_GPIO_BANK(7, 153, 164), +#endif +}; + +static void msm_gpio_irq_ack(unsigned int irq) +{ + unsigned long irq_flags; + struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); + spin_lock_irqsave(&msm_chip->lock, irq_flags); + msm_gpio_clear_detect_status(msm_chip, + irq - gpio_to_irq(msm_chip->chip.base)); + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); +} + +static void msm_gpio_irq_mask(unsigned int irq) +{ + unsigned long irq_flags; + struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); + unsigned offset = irq - gpio_to_irq(msm_chip->chip.base); + + spin_lock_irqsave(&msm_chip->lock, irq_flags); + /* level triggered interrupts are also latched */ + if (!(readl(msm_chip->regs.int_edge) & BIT(offset))) + msm_gpio_clear_detect_status(msm_chip, offset); + msm_chip->int_enable[0] &= ~BIT(offset); + writel(msm_chip->int_enable[0], msm_chip->regs.int_en); + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); +} + +static void msm_gpio_irq_unmask(unsigned int irq) +{ + unsigned long irq_flags; + struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); + unsigned offset = irq - gpio_to_irq(msm_chip->chip.base); + + spin_lock_irqsave(&msm_chip->lock, irq_flags); + /* level triggered interrupts are also latched */ + if (!(readl(msm_chip->regs.int_edge) & BIT(offset))) + msm_gpio_clear_detect_status(msm_chip, offset); + msm_chip->int_enable[0] |= BIT(offset); + writel(msm_chip->int_enable[0], msm_chip->regs.int_en); + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); +} + +static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on) +{ + unsigned long irq_flags; + struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); + unsigned offset = irq - gpio_to_irq(msm_chip->chip.base); + + spin_lock_irqsave(&msm_chip->lock, irq_flags); + + if (on) + msm_chip->int_enable[1] |= BIT(offset); + else + msm_chip->int_enable[1] &= ~BIT(offset); + + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); + return 0; +} + +static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + unsigned long irq_flags; + struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); + unsigned offset = irq - gpio_to_irq(msm_chip->chip.base); + unsigned val, mask = BIT(offset); + + spin_lock_irqsave(&msm_chip->lock, irq_flags); + val = readl(msm_chip->regs.int_edge); + if (flow_type & IRQ_TYPE_EDGE_BOTH) { + writel(val | mask, msm_chip->regs.int_edge); + irq_desc[irq].handle_irq = handle_edge_irq; + } else { + writel(val & ~mask, msm_chip->regs.int_edge); + irq_desc[irq].handle_irq = handle_level_irq; + } + if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { + msm_chip->both_edge_detect |= mask; + msm_gpio_update_both_edge_detect(msm_chip); + } else { + msm_chip->both_edge_detect &= ~mask; + val = readl(msm_chip->regs.int_pos); + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) + writel(val | mask, msm_chip->regs.int_pos); + else + writel(val & ~mask, msm_chip->regs.int_pos); } + spin_unlock_irqrestore(&msm_chip->lock, irq_flags); + return 0; } -EXPORT_SYMBOL(msm_gpios_disable); -int msm_gpios_request_enable(const struct msm_gpio *table, int size) +static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { - int rc = msm_gpios_enable(table, size); - return rc; + int i, j, mask; + unsigned val; + + for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) { + struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i]; + val = readl(msm_chip->regs.int_status); + val &= msm_chip->int_enable[0]; + while (val) { + mask = val & -val; + j = fls(mask) - 1; + /* printk("%s %08x %08x bit %d gpio %d irq %d\n", + __func__, v, m, j, msm_chip->chip.start + j, + FIRST_GPIO_IRQ + msm_chip->chip.start + j); */ + val &= ~mask; + generic_handle_irq(FIRST_GPIO_IRQ + + msm_chip->chip.base + j); + } + } + desc->chip->ack(irq); } -EXPORT_SYMBOL(msm_gpios_request_enable); -void msm_gpios_disable_free(const struct msm_gpio *table, int size) +static struct irq_chip msm_gpio_irq_chip = { + .name = "msmgpio", + .ack = msm_gpio_irq_ack, + .mask = msm_gpio_irq_mask, + .unmask = msm_gpio_irq_unmask, + .set_wake = msm_gpio_irq_set_wake, + .set_type = msm_gpio_irq_set_type, +}; + +static int __init msm_init_gpio(void) { - msm_gpios_disable(table, size); + int i, j = 0; + + for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) { + if (i - FIRST_GPIO_IRQ >= + msm_gpio_chips[j].chip.base + + msm_gpio_chips[j].chip.ngpio) + j++; + set_irq_chip_data(i, &msm_gpio_chips[j]); + set_irq_chip(i, &msm_gpio_irq_chip); + set_irq_handler(i, handle_edge_irq); + set_irq_flags(i, IRQF_VALID); + } + + for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) { + spin_lock_init(&msm_gpio_chips[i].lock); + writel(0, msm_gpio_chips[i].regs.int_en); + gpiochip_add(&msm_gpio_chips[i].chip); + } + + set_irq_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler); + set_irq_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler); + set_irq_wake(INT_GPIO_GROUP1, 1); + set_irq_wake(INT_GPIO_GROUP2, 2); + return 0; } -EXPORT_SYMBOL(msm_gpios_disable_free); + +postcore_initcall(msm_init_gpio); diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h new file mode 100644 index 0000000..6b50660 --- /dev/null +++ b/arch/arm/mach-msm/gpio_hw.h @@ -0,0 +1,278 @@ +/* arch/arm/mach-msm/gpio_hw.h + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H +#define __ARCH_ARM_MACH_MSM_GPIO_HW_H + +#include <mach/msm_iomap.h> + +/* see 80-VA736-2 Rev C pp 695-751 +** +** These are actually the *shadow* gpio registers, since the +** real ones (which allow full access) are only available to the +** ARM9 side of the world. +** +** Since the _BASE need to be page-aligned when we're mapping them +** to virtual addresses, adjust for the additional offset in these +** macros. +*/ + +#if defined(CONFIG_ARCH_MSM7X30) +#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off)) +#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off)) +#else +#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off)) +#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off)) +#endif + +#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\ + defined(CONFIG_ARCH_MSM7X27) + +/* output value */ +#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */ +#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */ +#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */ +#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */ +#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */ +#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 107-121 */ + +/* same pin map as above, output enable */ +#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10) +#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08) +#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14) +#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18) +#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C) +#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54) + +/* same pin map as above, input read */ +#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34) +#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20) +#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38) +#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C) +#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40) +#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44) + +/* same pin map as above, 1=edge 0=level interrup */ +#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60) +#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50) +#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64) +#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68) +#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C) +#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0) + +/* same pin map as above, 1=positive 0=negative */ +#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70) +#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58) +#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74) +#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78) +#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C) +#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC) + +/* same pin map as above, interrupt enable */ +#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80) +#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60) +#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84) +#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88) +#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C) +#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8) + +/* same pin map as above, write 1 to clear interrupt */ +#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90) +#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68) +#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94) +#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98) +#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C) +#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4) + +/* same pin map as above, 1=interrupt pending */ +#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0) +#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70) +#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4) +#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8) +#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC) +#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0) + +#endif + +#if defined(CONFIG_ARCH_QSD8X50) +/* output value */ +#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */ +#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */ +#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */ +#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */ +#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 103-95 */ +#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x10) /* gpio 121-104 */ +#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0x14) /* gpio 152-122 */ +#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x18) /* gpio 164-153 */ + +/* same pin map as above, output enable */ +#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x20) +#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08) +#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x24) +#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x28) +#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x2C) +#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x30) +#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0x34) +#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x38) + +/* same pin map as above, input read */ +#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x50) +#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20) +#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x54) +#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x58) +#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x5C) +#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x60) +#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0x64) +#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x68) + +/* same pin map as above, 1=edge 0=level interrup */ +#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x70) +#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50) +#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x74) +#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x78) +#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x7C) +#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0x80) +#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0x84) +#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x88) + +/* same pin map as above, 1=positive 0=negative */ +#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x90) +#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58) +#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x94) +#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x98) +#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x9C) +#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xA0) +#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xA4) +#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0xA8) + +/* same pin map as above, interrupt enable */ +#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0xB0) +#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60) +#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0xB4) +#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0xB8) +#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0xBC) +#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xC0) +#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xC4) +#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0xC8) + +/* same pin map as above, write 1 to clear interrupt */ +#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0xD0) +#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68) +#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0xD4) +#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0xD8) +#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0xDC) +#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xE0) +#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xE4) +#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0xE8) + +/* same pin map as above, 1=interrupt pending */ +#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xF0) +#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70) +#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xF4) +#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xF8) +#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xFC) +#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0x100) +#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0x104) +#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x108) + +#endif + +#if defined(CONFIG_ARCH_MSM7X30) + +/* output value */ +#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */ +#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 43-16 */ +#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-44 */ +#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */ +#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */ +#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 133-107 */ +#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0xC4) /* gpio 150-134 */ +#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x214) /* gpio 181-151 */ + +/* same pin map as above, output enable */ +#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10) +#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08) +#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14) +#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18) +#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C) +#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54) +#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0xC8) +#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x218) + +/* same pin map as above, input read */ +#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34) +#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20) +#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38) +#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C) +#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40) +#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44) +#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0xCC) +#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x21C) + +/* same pin map as above, 1=edge 0=level interrup */ +#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60) +#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50) +#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64) +#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68) +#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C) +#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0) +#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0xD0) +#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x240) + +/* same pin map as above, 1=positive 0=negative */ +#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70) +#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58) +#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74) +#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78) +#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C) +#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC) +#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4) +#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228) + +/* same pin map as above, interrupt enable */ +#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80) +#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60) +#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84) +#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88) +#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C) +#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8) +#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xD8) +#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0x22C) + +/* same pin map as above, write 1 to clear interrupt */ +#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90) +#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68) +#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94) +#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98) +#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C) +#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4) +#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xDC) +#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0x230) + +/* same pin map as above, 1=interrupt pending */ +#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0) +#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70) +#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4) +#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8) +#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC) +#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0) +#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0xE0) +#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x234) + +#endif + +#endif diff --git a/arch/arm/mach-msm/gpiomux-7x30.c b/arch/arm/mach-msm/gpiomux-7x30.c new file mode 100644 index 0000000..6ce41c5 --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-7x30.c @@ -0,0 +1,38 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include "gpiomux.h" + +struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { +#ifdef CONFIG_SERIAL_MSM_CONSOLE + [49] = { /* UART2 RFR */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, + [50] = { /* UART2 CTS */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, + [51] = { /* UART2 RX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, + [52] = { /* UART2 TX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, +#endif +}; diff --git a/arch/arm/mach-msm/gpiomux-8x50.c b/arch/arm/mach-msm/gpiomux-8x50.c new file mode 100644 index 0000000..4406e0f --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-8x50.c @@ -0,0 +1,28 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include "gpiomux.h" + +struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { + [86] = { /* UART3 RX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_1 | GPIOMUX_VALID, + }, + [87] = { /* UART3 TX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_1 | GPIOMUX_VALID, + }, +}; diff --git a/arch/arm/mach-msm/gpiomux-8x60.c b/arch/arm/mach-msm/gpiomux-8x60.c new file mode 100644 index 0000000..7b380b3 --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-8x60.c @@ -0,0 +1,19 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include "gpiomux.h" + +struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {}; diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c new file mode 100644 index 0000000..27de2ab --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v1.c @@ -0,0 +1,33 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/kernel.h> +#include "gpiomux.h" +#include "proc_comm.h" + +void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val) +{ + unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) | + ((gpio & 0x3ff) << 4); + unsigned tlmm_disable = 0; + int rc; + + rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, + &tlmm_config, &tlmm_disable); + if (rc) + pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n", + __func__, rc, tlmm_config, tlmm_disable); +} diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h new file mode 100644 index 0000000..71d86fe --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v1.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H +#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H + +#if defined(CONFIG_ARCH_MSM7X30) +#define GPIOMUX_NGPIOS 182 +#elif defined(CONFIG_ARCH_QSD8X50) +#define GPIOMUX_NGPIOS 165 +#else +#define GPIOMUX_NGPIOS 133 +#endif + +typedef u32 gpiomux_config_t; + +enum { + GPIOMUX_DRV_2MA = 0UL << 17, + GPIOMUX_DRV_4MA = 1UL << 17, + GPIOMUX_DRV_6MA = 2UL << 17, + GPIOMUX_DRV_8MA = 3UL << 17, + GPIOMUX_DRV_10MA = 4UL << 17, + GPIOMUX_DRV_12MA = 5UL << 17, + GPIOMUX_DRV_14MA = 6UL << 17, + GPIOMUX_DRV_16MA = 7UL << 17, +}; + +enum { + GPIOMUX_FUNC_GPIO = 0UL, + GPIOMUX_FUNC_1 = 1UL, + GPIOMUX_FUNC_2 = 2UL, + GPIOMUX_FUNC_3 = 3UL, + GPIOMUX_FUNC_4 = 4UL, + GPIOMUX_FUNC_5 = 5UL, + GPIOMUX_FUNC_6 = 6UL, + GPIOMUX_FUNC_7 = 7UL, + GPIOMUX_FUNC_8 = 8UL, + GPIOMUX_FUNC_9 = 9UL, + GPIOMUX_FUNC_A = 10UL, + GPIOMUX_FUNC_B = 11UL, + GPIOMUX_FUNC_C = 12UL, + GPIOMUX_FUNC_D = 13UL, + GPIOMUX_FUNC_E = 14UL, + GPIOMUX_FUNC_F = 15UL, +}; + +enum { + GPIOMUX_PULL_NONE = 0UL << 15, + GPIOMUX_PULL_DOWN = 1UL << 15, + GPIOMUX_PULL_KEEPER = 2UL << 15, + GPIOMUX_PULL_UP = 3UL << 15, +}; + +#endif diff --git a/arch/arm/mach-msm/gpiomux-v2.c b/arch/arm/mach-msm/gpiomux-v2.c new file mode 100644 index 0000000..273396d --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v2.c @@ -0,0 +1,25 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/io.h> +#include <mach/msm_iomap.h> +#include "gpiomux.h" + +void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val) +{ + writel(val & ~GPIOMUX_CTL_MASK, + MSM_TLMM_BASE + 0x1000 + (0x10 * gpio)); +} diff --git a/arch/arm/mach-msm/gpiomux-v2.h b/arch/arm/mach-msm/gpiomux-v2.h new file mode 100644 index 0000000..3bf10e7 --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v2.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H +#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H + +#define GPIOMUX_NGPIOS 173 + +typedef u16 gpiomux_config_t; + +enum { + GPIOMUX_DRV_2MA = 0UL << 6, + GPIOMUX_DRV_4MA = 1UL << 6, + GPIOMUX_DRV_6MA = 2UL << 6, + GPIOMUX_DRV_8MA = 3UL << 6, + GPIOMUX_DRV_10MA = 4UL << 6, + GPIOMUX_DRV_12MA = 5UL << 6, + GPIOMUX_DRV_14MA = 6UL << 6, + GPIOMUX_DRV_16MA = 7UL << 6, +}; + +enum { + GPIOMUX_FUNC_GPIO = 0UL << 2, + GPIOMUX_FUNC_1 = 1UL << 2, + GPIOMUX_FUNC_2 = 2UL << 2, + GPIOMUX_FUNC_3 = 3UL << 2, + GPIOMUX_FUNC_4 = 4UL << 2, + GPIOMUX_FUNC_5 = 5UL << 2, + GPIOMUX_FUNC_6 = 6UL << 2, + GPIOMUX_FUNC_7 = 7UL << 2, + GPIOMUX_FUNC_8 = 8UL << 2, + GPIOMUX_FUNC_9 = 9UL << 2, + GPIOMUX_FUNC_A = 10UL << 2, + GPIOMUX_FUNC_B = 11UL << 2, + GPIOMUX_FUNC_C = 12UL << 2, + GPIOMUX_FUNC_D = 13UL << 2, + GPIOMUX_FUNC_E = 14UL << 2, + GPIOMUX_FUNC_F = 15UL << 2, +}; + +enum { + GPIOMUX_PULL_NONE = 0UL, + GPIOMUX_PULL_DOWN = 1UL, + GPIOMUX_PULL_KEEPER = 2UL, + GPIOMUX_PULL_UP = 3UL, +}; + +#endif diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c new file mode 100644 index 0000000..53af21a --- /dev/null +++ b/arch/arm/mach-msm/gpiomux.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/module.h> +#include <linux/spinlock.h> +#include "gpiomux.h" + +static DEFINE_SPINLOCK(gpiomux_lock); + +int msm_gpiomux_write(unsigned gpio, + gpiomux_config_t active, + gpiomux_config_t suspended) +{ + struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio; + unsigned long irq_flags; + gpiomux_config_t setting; + + if (gpio >= GPIOMUX_NGPIOS) + return -EINVAL; + + spin_lock_irqsave(&gpiomux_lock, irq_flags); + + if (active & GPIOMUX_VALID) + cfg->active = active; + + if (suspended & GPIOMUX_VALID) + cfg->suspended = suspended; + + setting = cfg->ref ? active : suspended; + if (setting & GPIOMUX_VALID) + __msm_gpiomux_write(gpio, setting); + + spin_unlock_irqrestore(&gpiomux_lock, irq_flags); + return 0; +} +EXPORT_SYMBOL(msm_gpiomux_write); + +int msm_gpiomux_get(unsigned gpio) +{ + struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio; + unsigned long irq_flags; + + if (gpio >= GPIOMUX_NGPIOS) + return -EINVAL; + + spin_lock_irqsave(&gpiomux_lock, irq_flags); + if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID) + __msm_gpiomux_write(gpio, cfg->active); + spin_unlock_irqrestore(&gpiomux_lock, irq_flags); + return 0; +} +EXPORT_SYMBOL(msm_gpiomux_get); + +int msm_gpiomux_put(unsigned gpio) +{ + struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio; + unsigned long irq_flags; + + if (gpio >= GPIOMUX_NGPIOS) + return -EINVAL; + + spin_lock_irqsave(&gpiomux_lock, irq_flags); + BUG_ON(cfg->ref == 0); + if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID) + __msm_gpiomux_write(gpio, cfg->suspended); + spin_unlock_irqrestore(&gpiomux_lock, irq_flags); + return 0; +} +EXPORT_SYMBOL(msm_gpiomux_put); + +static int __init gpiomux_init(void) +{ + unsigned n; + + for (n = 0; n < GPIOMUX_NGPIOS; ++n) { + msm_gpiomux_configs[n].ref = 0; + if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID)) + continue; + __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended); + } + return 0; +} +postcore_initcall(gpiomux_init); diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h new file mode 100644 index 0000000..b178d9c --- /dev/null +++ b/arch/arm/mach-msm/gpiomux.h @@ -0,0 +1,114 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H +#define __ARCH_ARM_MACH_MSM_GPIOMUX_H + +#include <linux/bitops.h> +#include <linux/errno.h> + +#if defined(CONFIG_MSM_V2_TLMM) +#include "gpiomux-v2.h" +#else +#include "gpiomux-v1.h" +#endif + +/** + * struct msm_gpiomux_config: gpiomux settings for one gpio line. + * + * A complete gpiomux config is the bitwise-or of a drive-strength, + * function, and pull. For functions other than GPIO, the OE + * is hard-wired according to the function. For GPIO mode, + * OE is controlled by gpiolib. + * + * Available settings differ by target; see the gpiomux header + * specific to your target arch for available configurations. + * + * @active: The configuration to be installed when the line is + * active, or its reference count is > 0. + * @suspended: The configuration to be installed when the line + * is suspended, or its reference count is 0. + * @ref: The reference count of the line. For internal use of + * the gpiomux framework only. + */ +struct msm_gpiomux_config { + gpiomux_config_t active; + gpiomux_config_t suspended; + unsigned ref; +}; + +/** + * @GPIOMUX_VALID: If set, the config field contains 'good data'. + * The absence of this bit will prevent the gpiomux + * system from applying the configuration under all + * circumstances. + */ +enum { + GPIOMUX_VALID = BIT(sizeof(gpiomux_config_t) * BITS_PER_BYTE - 1), + GPIOMUX_CTL_MASK = GPIOMUX_VALID, +}; + +#ifdef CONFIG_MSM_GPIOMUX + +/* Each architecture must provide its own instance of this table. + * To avoid having gpiomux manage any given gpio, one or both of + * the entries can avoid setting GPIOMUX_VALID - the absence + * of that flag will prevent the configuration from being applied + * during state transitions. + */ +extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS]; + +/* Increment a gpio's reference count, possibly activating the line. */ +int __must_check msm_gpiomux_get(unsigned gpio); + +/* Decrement a gpio's reference count, possibly suspending the line. */ +int msm_gpiomux_put(unsigned gpio); + +/* Install a new configuration to the gpio line. To avoid overwriting + * a configuration, leave the VALID bit out. + */ +int msm_gpiomux_write(unsigned gpio, + gpiomux_config_t active, + gpiomux_config_t suspended); + +/* Architecture-internal function for use by the framework only. + * This function can assume the following: + * - the gpio value has passed a bounds-check + * - the gpiomux spinlock has been obtained + * + * This function is not for public consumption. External users + * should use msm_gpiomux_write. + */ +void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val); +#else +static inline int __must_check msm_gpiomux_get(unsigned gpio) +{ + return -ENOSYS; +} + +static inline int msm_gpiomux_put(unsigned gpio) +{ + return -ENOSYS; +} + +static inline int msm_gpiomux_write(unsigned gpio, + gpiomux_config_t active, + gpiomux_config_t suspended) +{ + return -ENOSYS; +} +#endif +#endif diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h index 5a79bcf..6abf4a6 100644 --- a/arch/arm/mach-msm/include/mach/board.h +++ b/arch/arm/mach-msm/include/mach/board.h @@ -33,6 +33,8 @@ struct msm_acpu_clock_platform_data struct clk; +extern struct sys_timer msm_timer; + /* common init routines for use by arch/arm/mach-msm/board-*.c */ void __init msm_add_devices(void); diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S index 528750f..238c4f1 100644 --- a/arch/arm/mach-msm/include/mach/debug-macro.S +++ b/arch/arm/mach-msm/include/mach/debug-macro.S @@ -19,7 +19,7 @@ #include <mach/hardware.h> #include <mach/msm_iomap.h> -#ifdef CONFIG_MSM_DEBUG_UART +#ifdef CONFIG_HAS_MSM_DEBUG_UART_PHYS .macro addruart, rx, tmp @ see if the MMU is enabled and select appropriate base address mrc p15, 0, \rx, c1, c0 diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h index 00f9bbf..05583f5 100644 --- a/arch/arm/mach-msm/include/mach/dma.h +++ b/arch/arm/mach-msm/include/mach/dma.h @@ -32,10 +32,18 @@ struct msm_dmov_cmd { void *data; }; +#ifndef CONFIG_ARCH_MSM8X60 void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful); int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr); - +#else +static inline +void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { } +static inline +void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { } +static inline +int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; } +#endif #define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2)) diff --git a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S new file mode 100644 index 0000000..4dc99aa --- /dev/null +++ b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S @@ -0,0 +1,88 @@ +/* + * Low-level IRQ helper macros + * + * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <mach/hardware.h> +#include <asm/hardware/gic.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Migrated the code from ARM MP port to be more consistant + * with interrupt processing , the following still holds true + * however, all interrupts are treated the same regardless of + * if they are local IPI or PPI + * + * Interrupts 0-15 are IPI + * 16-31 are PPI + * (16-18 are the timers) + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * A simple read from the controller will tell us the number of the + * highest priority enabled interrupt. We then just need to check + * whether it is in the valid range for an IRQ (0-1020 inclusive). + * + * Base ARM code assumes that the local (private) peripheral interrupts + * are not valid, we treat them differently, in that the privates are + * handled like normal shared interrupts with the exception that only + * one processor can register the interrupt and the handler must be + * the same for all processors. + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU, + 9-0 =int # */ + + bic \irqnr, \irqstat, #0x1c00 @mask src + cmp \irqnr, #15 + ldr \tmp, =1021 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #16 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/arch/arm/mach-msm/include/mach/entry-macro-vic.S b/arch/arm/mach-msm/include/mach/entry-macro-vic.S new file mode 100644 index 0000000..70563ed --- /dev/null +++ b/arch/arm/mach-msm/include/mach/entry-macro-vic.S @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <mach/msm_iomap.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + @ enable imprecise aborts + cpsie a + mov \base, #MSM_VIC_BASE + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + @ 0xD0 has irq# or old irq# if the irq has been handled + @ 0xD4 has irq# or -1 if none pending *but* if you just + @ read 0xD4 you never get the first irq for some reason + ldr \irqnr, [\base, #0xD0] + ldr \irqnr, [\base, #0xD4] + cmp \irqnr, #0xffffffff + .endm diff --git a/arch/arm/mach-msm/include/mach/entry-macro.S b/arch/arm/mach-msm/include/mach/entry-macro.S index d225948..b16f082 100644 --- a/arch/arm/mach-msm/include/mach/entry-macro.S +++ b/arch/arm/mach-msm/include/mach/entry-macro.S @@ -1,38 +1,23 @@ -/* arch/arm/mach-msm7200/include/mach/entry-macro.S +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. * - * Copyright (C) 2007 Google, Inc. - * Author: Brian Swetland <swetland@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * */ -#include <mach/msm_iomap.h> - - .macro disable_fiq - .endm - - .macro get_irqnr_preamble, base, tmp - @ enable imprecise aborts - cpsie a - mov \base, #MSM_VIC_BASE - .endm - - .macro arch_ret_to_user, tmp1, tmp2 - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - @ 0xD0 has irq# or old irq# if the irq has been handled - @ 0xD4 has irq# or -1 if none pending *but* if you just - @ read 0xD4 you never get the first irq for some reason - ldr \irqnr, [\base, #0xD0] - ldr \irqnr, [\base, #0xD4] - cmp \irqnr, #0xffffffff - .endm +#if defined(CONFIG_ARM_GIC) +#include <mach/entry-macro-qgic.S> +#else +#include <mach/entry-macro-vic.S> +#endif diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h index 83e47c0..36ad50d 100644 --- a/arch/arm/mach-msm/include/mach/gpio.h +++ b/arch/arm/mach-msm/include/mach/gpio.h @@ -23,127 +23,4 @@ #define gpio_cansleep __gpio_cansleep #define gpio_to_irq __gpio_to_irq -/** - * struct msm_gpio - GPIO pin description - * @gpio_cfg - configuration bitmap, as per gpio_tlmm_config() - * @label - textual label - * - * Usually, GPIO's are operated by sets. - * This struct accumulate all GPIO information in single source - * and facilitete group operations provided by msm_gpios_xxx() - */ -struct msm_gpio { - u32 gpio_cfg; - const char *label; -}; - -/** - * msm_gpios_request_enable() - request and enable set of GPIOs - * - * Request and configure set of GPIO's - * In case of error, all operations rolled back. - * Return error code. - * - * @table: GPIO table - * @size: number of entries in @table - */ -int msm_gpios_request_enable(const struct msm_gpio *table, int size); - -/** - * msm_gpios_disable_free() - disable and free set of GPIOs - * - * @table: GPIO table - * @size: number of entries in @table - */ -void msm_gpios_disable_free(const struct msm_gpio *table, int size); - -/** - * msm_gpios_request() - request set of GPIOs - * In case of error, all operations rolled back. - * Return error code. - * - * @table: GPIO table - * @size: number of entries in @table - */ -int msm_gpios_request(const struct msm_gpio *table, int size); - -/** - * msm_gpios_free() - free set of GPIOs - * - * @table: GPIO table - * @size: number of entries in @table - */ -void msm_gpios_free(const struct msm_gpio *table, int size); - -/** - * msm_gpios_enable() - enable set of GPIOs - * In case of error, all operations rolled back. - * Return error code. - * - * @table: GPIO table - * @size: number of entries in @table - */ -int msm_gpios_enable(const struct msm_gpio *table, int size); - -/** - * msm_gpios_disable() - disable set of GPIOs - * - * @table: GPIO table - * @size: number of entries in @table - */ -void msm_gpios_disable(const struct msm_gpio *table, int size); - -/* GPIO TLMM (Top Level Multiplexing) Definitions */ - -/* GPIO TLMM: Function -- GPIO specific */ - -/* GPIO TLMM: Direction */ -enum { - GPIO_INPUT, - GPIO_OUTPUT, -}; - -/* GPIO TLMM: Pullup/Pulldown */ -enum { - GPIO_NO_PULL, - GPIO_PULL_DOWN, - GPIO_KEEPER, - GPIO_PULL_UP, -}; - -/* GPIO TLMM: Drive Strength */ -enum { - GPIO_2MA, - GPIO_4MA, - GPIO_6MA, - GPIO_8MA, - GPIO_10MA, - GPIO_12MA, - GPIO_14MA, - GPIO_16MA, -}; - -enum { - GPIO_ENABLE, - GPIO_DISABLE, -}; - -#define GPIO_CFG(gpio, func, dir, pull, drvstr) \ - ((((gpio) & 0x3FF) << 4) | \ - ((func) & 0xf) | \ - (((dir) & 0x1) << 14) | \ - (((pull) & 0x3) << 15) | \ - (((drvstr) & 0xF) << 17)) - -/** - * extract GPIO pin from bit-field used for gpio_tlmm_config - */ -#define GPIO_PIN(gpio_cfg) (((gpio_cfg) >> 4) & 0x3ff) -#define GPIO_FUNC(gpio_cfg) (((gpio_cfg) >> 0) & 0xf) -#define GPIO_DIR(gpio_cfg) (((gpio_cfg) >> 14) & 0x1) -#define GPIO_PULL(gpio_cfg) (((gpio_cfg) >> 15) & 0x3) -#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf) - -int gpio_tlmm_config(unsigned config, unsigned disable); - #endif /* __ASM_ARCH_MSM_GPIO_H */ diff --git a/arch/arm/mach-msm/include/mach/io.h b/arch/arm/mach-msm/include/mach/io.h index c35b29f..7386e73 100644 --- a/arch/arm/mach-msm/include/mach/io.h +++ b/arch/arm/mach-msm/include/mach/io.h @@ -28,6 +28,7 @@ void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int m void msm_map_qsd8x50_io(void); void msm_map_msm7x30_io(void); +void msm_map_msm8x60_io(void); extern unsigned int msm_shared_ram_phys; diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h new file mode 100644 index 0000000..218ef57 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/iommu.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef MSM_IOMMU_H +#define MSM_IOMMU_H + +#include <linux/interrupt.h> + +/* Maximum number of Machine IDs that we are allowing to be mapped to the same + * context bank. The number of MIDs mapped to the same CB does not affect + * performance, but there is a practical limit on how many distinct MIDs may + * be present. These mappings are typically determined at design time and are + * not expected to change at run time. + */ +#define MAX_NUM_MIDS 16 + +/** + * struct msm_iommu_dev - a single IOMMU hardware instance + * name Human-readable name given to this IOMMU HW instance + * clk_rate Rate to set for this IOMMU's clock, if applicable to this + * particular IOMMU. 0 means don't set a rate. + * -1 means it is an AXI clock with no valid rate + * + */ +struct msm_iommu_dev { + const char *name; + int clk_rate; +}; + +/** + * struct msm_iommu_ctx_dev - an IOMMU context bank instance + * name Human-readable name given to this context bank + * num Index of this context bank within the hardware + * mids List of Machine IDs that are to be mapped into this context + * bank, terminated by -1. The MID is a set of signals on the + * AXI bus that identifies the function associated with a specific + * memory request. (See ARM spec). + */ +struct msm_iommu_ctx_dev { + const char *name; + int num; + int mids[MAX_NUM_MIDS]; +}; + + +/** + * struct msm_iommu_drvdata - A single IOMMU hardware instance + * @base: IOMMU config port base address (VA) + * @irq: Interrupt number + * + * A msm_iommu_drvdata holds the global driver data about a single piece + * of an IOMMU hardware instance. + */ +struct msm_iommu_drvdata { + void __iomem *base; + int irq; +}; + +/** + * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance + * @num: Hardware context number of this context + * @pdev: Platform device associated wit this HW instance + * @attached_elm: List element for domains to track which devices are + * attached to them + * + * A msm_iommu_ctx_drvdata holds the driver data for a single context bank + * within each IOMMU hardware instance + */ +struct msm_iommu_ctx_drvdata { + int num; + struct platform_device *pdev; + struct list_head attached_elm; +}; + +/* + * Look up an IOMMU context device by its context name. NULL if none found. + * Useful for testing and drivers that do not yet fully have IOMMU stuff in + * their platform devices. + */ +struct device *msm_iommu_get_ctx(const char *ctx_name); + +/* + * Interrupt handler for the IOMMU context fault interrupt. Hooking the + * interrupt is not supported in the API yet, but this will print an error + * message and dump useful IOMMU registers. + */ +irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id); + +#endif diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h new file mode 100644 index 0000000..f9386d3 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h @@ -0,0 +1,1871 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H +#define __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H + +#define CTX_SHIFT 12 + +#define GET_GLOBAL_REG(reg, base) (readl((base) + (reg))) +#define GET_CTX_REG(reg, base, ctx) \ + (readl((base) + (reg) + ((ctx) << CTX_SHIFT))) + +#define SET_GLOBAL_REG(reg, base, val) writel((val), ((base) + (reg))) + +#define SET_CTX_REG(reg, base, ctx, val) \ + writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT))) + +/* Wrappers for numbered registers */ +#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v)) +#define GET_GLOBAL_REG_N(b, n, r) GET_GLOBAL_REG(b, ((r) + (n << 2))) + +/* Field wrappers */ +#define GET_GLOBAL_FIELD(b, r, F) GET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT) +#define GET_CONTEXT_FIELD(b, c, r, F) \ + GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT) + +#define SET_GLOBAL_FIELD(b, r, F, v) \ + SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v)) +#define SET_CONTEXT_FIELD(b, c, r, F, v) \ + SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v)) + +#define GET_FIELD(addr, mask, shift) ((readl(addr) >> (shift)) & (mask)) + +#define SET_FIELD(addr, mask, shift, v) \ +do { \ + int t = readl(addr); \ + writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\ +} while (0) + + +#define NUM_FL_PTE 4096 +#define NUM_SL_PTE 256 + +/* First-level page table bits */ +#define FL_BASE_MASK 0xFFFFFC00 +#define FL_TYPE_TABLE (1 << 0) +#define FL_TYPE_SECT (2 << 0) +#define FL_SUPERSECTION (1 << 18) +#define FL_AP_WRITE (1 << 10) +#define FL_AP_READ (1 << 11) +#define FL_SHARED (1 << 16) +#define FL_OFFSET(va) (((va) & 0xFFF00000) >> 20) + +/* Second-level page table bits */ +#define SL_BASE_MASK_LARGE 0xFFFF0000 +#define SL_BASE_MASK_SMALL 0xFFFFF000 +#define SL_TYPE_LARGE (1 << 0) +#define SL_TYPE_SMALL (2 << 0) +#define SL_AP0 (1 << 4) +#define SL_AP1 (2 << 4) +#define SL_SHARED (1 << 10) +#define SL_OFFSET(va) (((va) & 0xFF000) >> 12) + +/* Global register setters / getters */ +#define SET_M2VCBR_N(b, N, v) SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v)) +#define SET_CBACR_N(b, N, v) SET_GLOBAL_REG_N(CBACR_N, N, (b), (v)) +#define SET_TLBRSW(b, v) SET_GLOBAL_REG(TLBRSW, (b), (v)) +#define SET_TLBTR0(b, v) SET_GLOBAL_REG(TLBTR0, (b), (v)) +#define SET_TLBTR1(b, v) SET_GLOBAL_REG(TLBTR1, (b), (v)) +#define SET_TLBTR2(b, v) SET_GLOBAL_REG(TLBTR2, (b), (v)) +#define SET_TESTBUSCR(b, v) SET_GLOBAL_REG(TESTBUSCR, (b), (v)) +#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v)) +#define SET_TLBIVMID(b, v) SET_GLOBAL_REG(TLBIVMID, (b), (v)) +#define SET_CR(b, v) SET_GLOBAL_REG(CR, (b), (v)) +#define SET_EAR(b, v) SET_GLOBAL_REG(EAR, (b), (v)) +#define SET_ESR(b, v) SET_GLOBAL_REG(ESR, (b), (v)) +#define SET_ESRRESTORE(b, v) SET_GLOBAL_REG(ESRRESTORE, (b), (v)) +#define SET_ESYNR0(b, v) SET_GLOBAL_REG(ESYNR0, (b), (v)) +#define SET_ESYNR1(b, v) SET_GLOBAL_REG(ESYNR1, (b), (v)) +#define SET_RPU_ACR(b, v) SET_GLOBAL_REG(RPU_ACR, (b), (v)) + +#define GET_M2VCBR_N(b, N) GET_GLOBAL_REG_N(M2VCBR_N, N, (b)) +#define GET_CBACR_N(b, N) GET_GLOBAL_REG_N(CBACR_N, N, (b)) +#define GET_TLBTR0(b) GET_GLOBAL_REG(TLBTR0, (b)) +#define GET_TLBTR1(b) GET_GLOBAL_REG(TLBTR1, (b)) +#define GET_TLBTR2(b) GET_GLOBAL_REG(TLBTR2, (b)) +#define GET_TESTBUSCR(b) GET_GLOBAL_REG(TESTBUSCR, (b)) +#define GET_GLOBAL_TLBIALL(b) GET_GLOBAL_REG(GLOBAL_TLBIALL, (b)) +#define GET_TLBIVMID(b) GET_GLOBAL_REG(TLBIVMID, (b)) +#define GET_CR(b) GET_GLOBAL_REG(CR, (b)) +#define GET_EAR(b) GET_GLOBAL_REG(EAR, (b)) +#define GET_ESR(b) GET_GLOBAL_REG(ESR, (b)) +#define GET_ESRRESTORE(b) GET_GLOBAL_REG(ESRRESTORE, (b)) +#define GET_ESYNR0(b) GET_GLOBAL_REG(ESYNR0, (b)) +#define GET_ESYNR1(b) GET_GLOBAL_REG(ESYNR1, (b)) +#define GET_REV(b) GET_GLOBAL_REG(REV, (b)) +#define GET_IDR(b) GET_GLOBAL_REG(IDR, (b)) +#define GET_RPU_ACR(b) GET_GLOBAL_REG(RPU_ACR, (b)) + + +/* Context register setters/getters */ +#define SET_SCTLR(b, c, v) SET_CTX_REG(SCTLR, (b), (c), (v)) +#define SET_ACTLR(b, c, v) SET_CTX_REG(ACTLR, (b), (c), (v)) +#define SET_CONTEXTIDR(b, c, v) SET_CTX_REG(CONTEXTIDR, (b), (c), (v)) +#define SET_TTBR0(b, c, v) SET_CTX_REG(TTBR0, (b), (c), (v)) +#define SET_TTBR1(b, c, v) SET_CTX_REG(TTBR1, (b), (c), (v)) +#define SET_TTBCR(b, c, v) SET_CTX_REG(TTBCR, (b), (c), (v)) +#define SET_PAR(b, c, v) SET_CTX_REG(PAR, (b), (c), (v)) +#define SET_FSR(b, c, v) SET_CTX_REG(FSR, (b), (c), (v)) +#define SET_FSRRESTORE(b, c, v) SET_CTX_REG(FSRRESTORE, (b), (c), (v)) +#define SET_FAR(b, c, v) SET_CTX_REG(FAR, (b), (c), (v)) +#define SET_FSYNR0(b, c, v) SET_CTX_REG(FSYNR0, (b), (c), (v)) +#define SET_FSYNR1(b, c, v) SET_CTX_REG(FSYNR1, (b), (c), (v)) +#define SET_PRRR(b, c, v) SET_CTX_REG(PRRR, (b), (c), (v)) +#define SET_NMRR(b, c, v) SET_CTX_REG(NMRR, (b), (c), (v)) +#define SET_TLBLKCR(b, c, v) SET_CTX_REG(TLBLCKR, (b), (c), (v)) +#define SET_V2PSR(b, c, v) SET_CTX_REG(V2PSR, (b), (c), (v)) +#define SET_TLBFLPTER(b, c, v) SET_CTX_REG(TLBFLPTER, (b), (c), (v)) +#define SET_TLBSLPTER(b, c, v) SET_CTX_REG(TLBSLPTER, (b), (c), (v)) +#define SET_BFBCR(b, c, v) SET_CTX_REG(BFBCR, (b), (c), (v)) +#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v)) +#define SET_TLBIASID(b, c, v) SET_CTX_REG(TLBIASID, (b), (c), (v)) +#define SET_TLBIVA(b, c, v) SET_CTX_REG(TLBIVA, (b), (c), (v)) +#define SET_TLBIVAA(b, c, v) SET_CTX_REG(TLBIVAA, (b), (c), (v)) +#define SET_V2PPR(b, c, v) SET_CTX_REG(V2PPR, (b), (c), (v)) +#define SET_V2PPW(b, c, v) SET_CTX_REG(V2PPW, (b), (c), (v)) +#define SET_V2PUR(b, c, v) SET_CTX_REG(V2PUR, (b), (c), (v)) +#define SET_V2PUW(b, c, v) SET_CTX_REG(V2PUW, (b), (c), (v)) +#define SET_RESUME(b, c, v) SET_CTX_REG(RESUME, (b), (c), (v)) + +#define GET_SCTLR(b, c) GET_CTX_REG(SCTLR, (b), (c)) +#define GET_ACTLR(b, c) GET_CTX_REG(ACTLR, (b), (c)) +#define GET_CONTEXTIDR(b, c) GET_CTX_REG(CONTEXTIDR, (b), (c)) +#define GET_TTBR0(b, c) GET_CTX_REG(TTBR0, (b), (c)) +#define GET_TTBR1(b, c) GET_CTX_REG(TTBR1, (b), (c)) +#define GET_TTBCR(b, c) GET_CTX_REG(TTBCR, (b), (c)) +#define GET_PAR(b, c) GET_CTX_REG(PAR, (b), (c)) +#define GET_FSR(b, c) GET_CTX_REG(FSR, (b), (c)) +#define GET_FSRRESTORE(b, c) GET_CTX_REG(FSRRESTORE, (b), (c)) +#define GET_FAR(b, c) GET_CTX_REG(FAR, (b), (c)) +#define GET_FSYNR0(b, c) GET_CTX_REG(FSYNR0, (b), (c)) +#define GET_FSYNR1(b, c) GET_CTX_REG(FSYNR1, (b), (c)) +#define GET_PRRR(b, c) GET_CTX_REG(PRRR, (b), (c)) +#define GET_NMRR(b, c) GET_CTX_REG(NMRR, (b), (c)) +#define GET_TLBLCKR(b, c) GET_CTX_REG(TLBLCKR, (b), (c)) +#define GET_V2PSR(b, c) GET_CTX_REG(V2PSR, (b), (c)) +#define GET_TLBFLPTER(b, c) GET_CTX_REG(TLBFLPTER, (b), (c)) +#define GET_TLBSLPTER(b, c) GET_CTX_REG(TLBSLPTER, (b), (c)) +#define GET_BFBCR(b, c) GET_CTX_REG(BFBCR, (b), (c)) +#define GET_CTX_TLBIALL(b, c) GET_CTX_REG(CTX_TLBIALL, (b), (c)) +#define GET_TLBIASID(b, c) GET_CTX_REG(TLBIASID, (b), (c)) +#define GET_TLBIVA(b, c) GET_CTX_REG(TLBIVA, (b), (c)) +#define GET_TLBIVAA(b, c) GET_CTX_REG(TLBIVAA, (b), (c)) +#define GET_V2PPR(b, c) GET_CTX_REG(V2PPR, (b), (c)) +#define GET_V2PPW(b, c) GET_CTX_REG(V2PPW, (b), (c)) +#define GET_V2PUR(b, c) GET_CTX_REG(V2PUR, (b), (c)) +#define GET_V2PUW(b, c) GET_CTX_REG(V2PUW, (b), (c)) +#define GET_RESUME(b, c) GET_CTX_REG(RESUME, (b), (c)) + + +/* Global field setters / getters */ +/* Global Field Setters: */ +/* CBACR_N */ +#define SET_RWVMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID, v) +#define SET_RWE(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE, v) +#define SET_RWGE(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE, v) +#define SET_CBVMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID, v) +#define SET_IRPTNDX(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX, v) + + +/* M2VCBR_N */ +#define SET_VMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID, v) +#define SET_CBNDX(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX, v) +#define SET_BYPASSD(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD, v) +#define SET_BPRCOSH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH, v) +#define SET_BPRCISH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH, v) +#define SET_BPRCNSH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH, v) +#define SET_BPSHCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG, v) +#define SET_NSCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG, v) +#define SET_BPMTCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG, v) +#define SET_BPMEMTYPE(b, n, v) \ + SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE, v) + + +/* CR */ +#define SET_RPUE(b, v) SET_GLOBAL_FIELD(b, CR, RPUE, v) +#define SET_RPUERE(b, v) SET_GLOBAL_FIELD(b, CR, RPUERE, v) +#define SET_RPUEIE(b, v) SET_GLOBAL_FIELD(b, CR, RPUEIE, v) +#define SET_DCDEE(b, v) SET_GLOBAL_FIELD(b, CR, DCDEE, v) +#define SET_CLIENTPD(b, v) SET_GLOBAL_FIELD(b, CR, CLIENTPD, v) +#define SET_STALLD(b, v) SET_GLOBAL_FIELD(b, CR, STALLD, v) +#define SET_TLBLKCRWE(b, v) SET_GLOBAL_FIELD(b, CR, TLBLKCRWE, v) +#define SET_CR_TLBIALLCFG(b, v) SET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG, v) +#define SET_TLBIVMIDCFG(b, v) SET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG, v) +#define SET_CR_HUME(b, v) SET_GLOBAL_FIELD(b, CR, CR_HUME, v) + + +/* ESR */ +#define SET_CFG(b, v) SET_GLOBAL_FIELD(b, ESR, CFG, v) +#define SET_BYPASS(b, v) SET_GLOBAL_FIELD(b, ESR, BYPASS, v) +#define SET_ESR_MULTI(b, v) SET_GLOBAL_FIELD(b, ESR, ESR_MULTI, v) + + +/* ESYNR0 */ +#define SET_ESYNR0_AMID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID, v) +#define SET_ESYNR0_APID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID, v) +#define SET_ESYNR0_ABID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID, v) +#define SET_ESYNR0_AVMID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID, v) +#define SET_ESYNR0_ATID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID, v) + + +/* ESYNR1 */ +#define SET_ESYNR1_AMEMTYPE(b, v) \ + SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE, v) +#define SET_ESYNR1_ASHARED(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED, v) +#define SET_ESYNR1_AINNERSHARED(b, v) \ + SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED, v) +#define SET_ESYNR1_APRIV(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV, v) +#define SET_ESYNR1_APROTNS(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS, v) +#define SET_ESYNR1_AINST(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST, v) +#define SET_ESYNR1_AWRITE(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE, v) +#define SET_ESYNR1_ABURST(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST, v) +#define SET_ESYNR1_ALEN(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN, v) +#define SET_ESYNR1_ASIZE(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE, v) +#define SET_ESYNR1_ALOCK(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK, v) +#define SET_ESYNR1_AOOO(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO, v) +#define SET_ESYNR1_AFULL(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL, v) +#define SET_ESYNR1_AC(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC, v) +#define SET_ESYNR1_DCD(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD, v) + + +/* TESTBUSCR */ +#define SET_TBE(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBE, v) +#define SET_SPDMBE(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE, v) +#define SET_WGSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL, v) +#define SET_TBLSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL, v) +#define SET_TBHSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL, v) +#define SET_SPDM0SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL, v) +#define SET_SPDM1SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL, v) +#define SET_SPDM2SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL, v) +#define SET_SPDM3SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL, v) + + +/* TLBIVMID */ +#define SET_TLBIVMID_VMID(b, v) SET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID, v) + + +/* TLBRSW */ +#define SET_TLBRSW_INDEX(b, v) SET_GLOBAL_FIELD(b, TLBRSW, TLBRSW_INDEX, v) +#define SET_TLBBFBS(b, v) SET_GLOBAL_FIELD(b, TLBRSW, TLBBFBS, v) + + +/* TLBTR0 */ +#define SET_PR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, PR, v) +#define SET_PW(b, v) SET_GLOBAL_FIELD(b, TLBTR0, PW, v) +#define SET_UR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, UR, v) +#define SET_UW(b, v) SET_GLOBAL_FIELD(b, TLBTR0, UW, v) +#define SET_XN(b, v) SET_GLOBAL_FIELD(b, TLBTR0, XN, v) +#define SET_NSDESC(b, v) SET_GLOBAL_FIELD(b, TLBTR0, NSDESC, v) +#define SET_ISH(b, v) SET_GLOBAL_FIELD(b, TLBTR0, ISH, v) +#define SET_SH(b, v) SET_GLOBAL_FIELD(b, TLBTR0, SH, v) +#define SET_MT(b, v) SET_GLOBAL_FIELD(b, TLBTR0, MT, v) +#define SET_DPSIZR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, DPSIZR, v) +#define SET_DPSIZC(b, v) SET_GLOBAL_FIELD(b, TLBTR0, DPSIZC, v) + + +/* TLBTR1 */ +#define SET_TLBTR1_VMID(b, v) SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID, v) +#define SET_TLBTR1_PA(b, v) SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA, v) + + +/* TLBTR2 */ +#define SET_TLBTR2_ASID(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID, v) +#define SET_TLBTR2_V(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V, v) +#define SET_TLBTR2_NSTID(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID, v) +#define SET_TLBTR2_NV(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV, v) +#define SET_TLBTR2_VA(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA, v) + + +/* Global Field Getters */ +/* CBACR_N */ +#define GET_RWVMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID) +#define GET_RWE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE) +#define GET_RWGE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE) +#define GET_CBVMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID) +#define GET_IRPTNDX(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX) + + +/* M2VCBR_N */ +#define GET_VMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID) +#define GET_CBNDX(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX) +#define GET_BYPASSD(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD) +#define GET_BPRCOSH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH) +#define GET_BPRCISH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH) +#define GET_BPRCNSH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH) +#define GET_BPSHCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG) +#define GET_NSCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG) +#define GET_BPMTCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG) +#define GET_BPMEMTYPE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE) + + +/* CR */ +#define GET_RPUE(b) GET_GLOBAL_FIELD(b, CR, RPUE) +#define GET_RPUERE(b) GET_GLOBAL_FIELD(b, CR, RPUERE) +#define GET_RPUEIE(b) GET_GLOBAL_FIELD(b, CR, RPUEIE) +#define GET_DCDEE(b) GET_GLOBAL_FIELD(b, CR, DCDEE) +#define GET_CLIENTPD(b) GET_GLOBAL_FIELD(b, CR, CLIENTPD) +#define GET_STALLD(b) GET_GLOBAL_FIELD(b, CR, STALLD) +#define GET_TLBLKCRWE(b) GET_GLOBAL_FIELD(b, CR, TLBLKCRWE) +#define GET_CR_TLBIALLCFG(b) GET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG) +#define GET_TLBIVMIDCFG(b) GET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG) +#define GET_CR_HUME(b) GET_GLOBAL_FIELD(b, CR, CR_HUME) + + +/* ESR */ +#define GET_CFG(b) GET_GLOBAL_FIELD(b, ESR, CFG) +#define GET_BYPASS(b) GET_GLOBAL_FIELD(b, ESR, BYPASS) +#define GET_ESR_MULTI(b) GET_GLOBAL_FIELD(b, ESR, ESR_MULTI) + + +/* ESYNR0 */ +#define GET_ESYNR0_AMID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID) +#define GET_ESYNR0_APID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID) +#define GET_ESYNR0_ABID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID) +#define GET_ESYNR0_AVMID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID) +#define GET_ESYNR0_ATID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID) + + +/* ESYNR1 */ +#define GET_ESYNR1_AMEMTYPE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE) +#define GET_ESYNR1_ASHARED(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED) +#define GET_ESYNR1_AINNERSHARED(b) \ + GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED) +#define GET_ESYNR1_APRIV(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV) +#define GET_ESYNR1_APROTNS(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS) +#define GET_ESYNR1_AINST(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST) +#define GET_ESYNR1_AWRITE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE) +#define GET_ESYNR1_ABURST(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST) +#define GET_ESYNR1_ALEN(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN) +#define GET_ESYNR1_ASIZE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE) +#define GET_ESYNR1_ALOCK(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK) +#define GET_ESYNR1_AOOO(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO) +#define GET_ESYNR1_AFULL(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL) +#define GET_ESYNR1_AC(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC) +#define GET_ESYNR1_DCD(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD) + + +/* IDR */ +#define GET_NM2VCBMT(b) GET_GLOBAL_FIELD(b, IDR, NM2VCBMT) +#define GET_HTW(b) GET_GLOBAL_FIELD(b, IDR, HTW) +#define GET_HUM(b) GET_GLOBAL_FIELD(b, IDR, HUM) +#define GET_TLBSIZE(b) GET_GLOBAL_FIELD(b, IDR, TLBSIZE) +#define GET_NCB(b) GET_GLOBAL_FIELD(b, IDR, NCB) +#define GET_NIRPT(b) GET_GLOBAL_FIELD(b, IDR, NIRPT) + + +/* REV */ +#define GET_MAJOR(b) GET_GLOBAL_FIELD(b, REV, MAJOR) +#define GET_MINOR(b) GET_GLOBAL_FIELD(b, REV, MINOR) + + +/* TESTBUSCR */ +#define GET_TBE(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBE) +#define GET_SPDMBE(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE) +#define GET_WGSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL) +#define GET_TBLSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL) +#define GET_TBHSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL) +#define GET_SPDM0SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL) +#define GET_SPDM1SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL) +#define GET_SPDM2SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL) +#define GET_SPDM3SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL) + + +/* TLBIVMID */ +#define GET_TLBIVMID_VMID(b) GET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID) + + +/* TLBTR0 */ +#define GET_PR(b) GET_GLOBAL_FIELD(b, TLBTR0, PR) +#define GET_PW(b) GET_GLOBAL_FIELD(b, TLBTR0, PW) +#define GET_UR(b) GET_GLOBAL_FIELD(b, TLBTR0, UR) +#define GET_UW(b) GET_GLOBAL_FIELD(b, TLBTR0, UW) +#define GET_XN(b) GET_GLOBAL_FIELD(b, TLBTR0, XN) +#define GET_NSDESC(b) GET_GLOBAL_FIELD(b, TLBTR0, NSDESC) +#define GET_ISH(b) GET_GLOBAL_FIELD(b, TLBTR0, ISH) +#define GET_SH(b) GET_GLOBAL_FIELD(b, TLBTR0, SH) +#define GET_MT(b) GET_GLOBAL_FIELD(b, TLBTR0, MT) +#define GET_DPSIZR(b) GET_GLOBAL_FIELD(b, TLBTR0, DPSIZR) +#define GET_DPSIZC(b) GET_GLOBAL_FIELD(b, TLBTR0, DPSIZC) + + +/* TLBTR1 */ +#define GET_TLBTR1_VMID(b) GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID) +#define GET_TLBTR1_PA(b) GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA) + + +/* TLBTR2 */ +#define GET_TLBTR2_ASID(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID) +#define GET_TLBTR2_V(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V) +#define GET_TLBTR2_NSTID(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID) +#define GET_TLBTR2_NV(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV) +#define GET_TLBTR2_VA(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA) + + +/* Context Register setters / getters */ +/* Context Register setters */ +/* ACTLR */ +#define SET_CFERE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFERE, v) +#define SET_CFEIE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFEIE, v) +#define SET_PTSHCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG, v) +#define SET_RCOSH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCOSH, v) +#define SET_RCISH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCISH, v) +#define SET_RCNSH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCNSH, v) +#define SET_PRIVCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG, v) +#define SET_DNA(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, DNA, v) +#define SET_DNLV2PA(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA, v) +#define SET_TLBMCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG, v) +#define SET_CFCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFCFG, v) +#define SET_TIPCF(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, TIPCF, v) +#define SET_V2PCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG, v) +#define SET_HUME(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, HUME, v) +#define SET_PTMTCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG, v) +#define SET_PTMEMTYPE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE, v) + + +/* BFBCR */ +#define SET_BFBDFE(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE, v) +#define SET_BFBSFE(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE, v) +#define SET_SFVS(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, SFVS, v) +#define SET_FLVIC(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, FLVIC, v) +#define SET_SLVIC(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, SLVIC, v) + + +/* CONTEXTIDR */ +#define SET_CONTEXTIDR_ASID(b, c, v) \ + SET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID, v) +#define SET_CONTEXTIDR_PROCID(b, c, v) \ + SET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID, v) + + +/* FSR */ +#define SET_TF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, TF, v) +#define SET_AFF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, AFF, v) +#define SET_APF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, APF, v) +#define SET_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, TLBMF, v) +#define SET_HTWDEEF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, HTWDEEF, v) +#define SET_HTWSEEF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, HTWSEEF, v) +#define SET_MHF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, MHF, v) +#define SET_SL(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, SL, v) +#define SET_SS(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, SS, v) +#define SET_MULTI(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, MULTI, v) + + +/* FSYNR0 */ +#define SET_AMID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, AMID, v) +#define SET_APID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, APID, v) +#define SET_ABID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, ABID, v) +#define SET_ATID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, ATID, v) + + +/* FSYNR1 */ +#define SET_AMEMTYPE(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE, v) +#define SET_ASHARED(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED, v) +#define SET_AINNERSHARED(b, c, v) \ + SET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED, v) +#define SET_APRIV(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, APRIV, v) +#define SET_APROTNS(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS, v) +#define SET_AINST(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AINST, v) +#define SET_AWRITE(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE, v) +#define SET_ABURST(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ABURST, v) +#define SET_ALEN(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ALEN, v) +#define SET_FSYNR1_ASIZE(b, c, v) \ + SET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE, v) +#define SET_ALOCK(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK, v) +#define SET_AFULL(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AFULL, v) + + +/* NMRR */ +#define SET_ICPC0(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC0, v) +#define SET_ICPC1(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC1, v) +#define SET_ICPC2(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC2, v) +#define SET_ICPC3(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC3, v) +#define SET_ICPC4(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC4, v) +#define SET_ICPC5(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC5, v) +#define SET_ICPC6(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC6, v) +#define SET_ICPC7(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC7, v) +#define SET_OCPC0(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC0, v) +#define SET_OCPC1(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC1, v) +#define SET_OCPC2(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC2, v) +#define SET_OCPC3(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC3, v) +#define SET_OCPC4(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC4, v) +#define SET_OCPC5(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC5, v) +#define SET_OCPC6(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC6, v) +#define SET_OCPC7(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC7, v) + + +/* PAR */ +#define SET_FAULT(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT, v) + +#define SET_FAULT_TF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TF, v) +#define SET_FAULT_AFF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF, v) +#define SET_FAULT_APF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_APF, v) +#define SET_FAULT_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF, v) +#define SET_FAULT_HTWDEEF(b, c, v) \ + SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF, v) +#define SET_FAULT_HTWSEEF(b, c, v) \ + SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF, v) +#define SET_FAULT_MHF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF, v) +#define SET_FAULT_SL(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_SL, v) +#define SET_FAULT_SS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_SS, v) + +#define SET_NOFAULT_SS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SS, v) +#define SET_NOFAULT_MT(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_MT, v) +#define SET_NOFAULT_SH(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SH, v) +#define SET_NOFAULT_NS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NS, v) +#define SET_NOFAULT_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NOS, v) +#define SET_NPFAULT_PA(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NPFAULT_PA, v) + + +/* PRRR */ +#define SET_MTC0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC0, v) +#define SET_MTC1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC1, v) +#define SET_MTC2(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC2, v) +#define SET_MTC3(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC3, v) +#define SET_MTC4(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC4, v) +#define SET_MTC5(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC5, v) +#define SET_MTC6(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC6, v) +#define SET_MTC7(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC7, v) +#define SET_SHDSH0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHDSH0, v) +#define SET_SHDSH1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHDSH1, v) +#define SET_SHNMSH0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0, v) +#define SET_SHNMSH1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1, v) +#define SET_NOS0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS0, v) +#define SET_NOS1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS1, v) +#define SET_NOS2(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS2, v) +#define SET_NOS3(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS3, v) +#define SET_NOS4(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS4, v) +#define SET_NOS5(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS5, v) +#define SET_NOS6(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS6, v) +#define SET_NOS7(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS7, v) + + +/* RESUME */ +#define SET_TNR(b, c, v) SET_CONTEXT_FIELD(b, c, RESUME, TNR, v) + + +/* SCTLR */ +#define SET_M(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, M, v) +#define SET_TRE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, TRE, v) +#define SET_AFE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, AFE, v) +#define SET_HAF(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, HAF, v) +#define SET_BE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, BE, v) +#define SET_AFFD(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, AFFD, v) + + +/* TLBLKCR */ +#define SET_LKE(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, LKE, v) +#define SET_TLBLKCR_TLBIALLCFG(b, c, v) \ + SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG, v) +#define SET_TLBIASIDCFG(b, c, v) \ + SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG, v) +#define SET_TLBIVAACFG(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG, v) +#define SET_FLOOR(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR, v) +#define SET_VICTIM(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM, v) + + +/* TTBCR */ +#define SET_N(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, N, v) +#define SET_PD0(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, PD0, v) +#define SET_PD1(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, PD1, v) + + +/* TTBR0 */ +#define SET_TTBR0_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH, v) +#define SET_TTBR0_SH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH, v) +#define SET_TTBR0_ORGN(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN, v) +#define SET_TTBR0_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS, v) +#define SET_TTBR0_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL, v) +#define SET_TTBR0_PA(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA, v) + + +/* TTBR1 */ +#define SET_TTBR1_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH, v) +#define SET_TTBR1_SH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH, v) +#define SET_TTBR1_ORGN(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN, v) +#define SET_TTBR1_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS, v) +#define SET_TTBR1_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL, v) +#define SET_TTBR1_PA(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA, v) + + +/* V2PSR */ +#define SET_HIT(b, c, v) SET_CONTEXT_FIELD(b, c, V2PSR, HIT, v) +#define SET_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v) + + +/* V2Pxx UW UR PW PR */ +#define SET_V2PUW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX, v) +#define SET_V2PUW_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA, v) + +#define SET_V2PUR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX, v) +#define SET_V2PUR_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA, v) + +#define SET_V2PPW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX, v) +#define SET_V2PPW_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA, v) + +#define SET_V2PPR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX, v) +#define SET_V2PPR_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA, v) + + +/* Context Register getters */ +/* ACTLR */ +#define GET_CFERE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFERE) +#define GET_CFEIE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFEIE) +#define GET_PTSHCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG) +#define GET_RCOSH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCOSH) +#define GET_RCISH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCISH) +#define GET_RCNSH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCNSH) +#define GET_PRIVCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG) +#define GET_DNA(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, DNA) +#define GET_DNLV2PA(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA) +#define GET_TLBMCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG) +#define GET_CFCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFCFG) +#define GET_TIPCF(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, TIPCF) +#define GET_V2PCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG) +#define GET_HUME(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, HUME) +#define GET_PTMTCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG) +#define GET_PTMEMTYPE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE) + +/* BFBCR */ +#define GET_BFBDFE(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE) +#define GET_BFBSFE(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE) +#define GET_SFVS(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, SFVS) +#define GET_FLVIC(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, FLVIC) +#define GET_SLVIC(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, SLVIC) + + +/* CONTEXTIDR */ +#define GET_CONTEXTIDR_ASID(b, c) \ + GET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID) +#define GET_CONTEXTIDR_PROCID(b, c) GET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID) + + +/* FSR */ +#define GET_TF(b, c) GET_CONTEXT_FIELD(b, c, FSR, TF) +#define GET_AFF(b, c) GET_CONTEXT_FIELD(b, c, FSR, AFF) +#define GET_APF(b, c) GET_CONTEXT_FIELD(b, c, FSR, APF) +#define GET_TLBMF(b, c) GET_CONTEXT_FIELD(b, c, FSR, TLBMF) +#define GET_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, FSR, HTWDEEF) +#define GET_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, FSR, HTWSEEF) +#define GET_MHF(b, c) GET_CONTEXT_FIELD(b, c, FSR, MHF) +#define GET_SL(b, c) GET_CONTEXT_FIELD(b, c, FSR, SL) +#define GET_SS(b, c) GET_CONTEXT_FIELD(b, c, FSR, SS) +#define GET_MULTI(b, c) GET_CONTEXT_FIELD(b, c, FSR, MULTI) + + +/* FSYNR0 */ +#define GET_AMID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, AMID) +#define GET_APID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, APID) +#define GET_ABID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, ABID) +#define GET_ATID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, ATID) + + +/* FSYNR1 */ +#define GET_AMEMTYPE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE) +#define GET_ASHARED(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED) +#define GET_AINNERSHARED(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED) +#define GET_APRIV(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, APRIV) +#define GET_APROTNS(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS) +#define GET_AINST(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AINST) +#define GET_AWRITE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE) +#define GET_ABURST(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ABURST) +#define GET_ALEN(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ALEN) +#define GET_FSYNR1_ASIZE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE) +#define GET_ALOCK(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK) +#define GET_AFULL(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AFULL) + + +/* NMRR */ +#define GET_ICPC0(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC0) +#define GET_ICPC1(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC1) +#define GET_ICPC2(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC2) +#define GET_ICPC3(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC3) +#define GET_ICPC4(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC4) +#define GET_ICPC5(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC5) +#define GET_ICPC6(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC6) +#define GET_ICPC7(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC7) +#define GET_OCPC0(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC0) +#define GET_OCPC1(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC1) +#define GET_OCPC2(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC2) +#define GET_OCPC3(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC3) +#define GET_OCPC4(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC4) +#define GET_OCPC5(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC5) +#define GET_OCPC6(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC6) +#define GET_OCPC7(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC7) + + +/* PAR */ +#define GET_FAULT(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT) + +#define GET_FAULT_TF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_TF) +#define GET_FAULT_AFF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF) +#define GET_FAULT_APF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_APF) +#define GET_FAULT_TLBMF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF) +#define GET_FAULT_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF) +#define GET_FAULT_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF) +#define GET_FAULT_MHF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF) +#define GET_FAULT_SL(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_SL) +#define GET_FAULT_SS(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_SS) + +#define GET_NOFAULT_SS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SS) +#define GET_NOFAULT_MT(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_MT) +#define GET_NOFAULT_SH(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SH) +#define GET_NOFAULT_NS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NS) +#define GET_NOFAULT_NOS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NOS) +#define GET_NPFAULT_PA(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NPFAULT_PA) + + +/* PRRR */ +#define GET_MTC0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC0) +#define GET_MTC1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC1) +#define GET_MTC2(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC2) +#define GET_MTC3(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC3) +#define GET_MTC4(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC4) +#define GET_MTC5(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC5) +#define GET_MTC6(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC6) +#define GET_MTC7(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC7) +#define GET_SHDSH0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHDSH0) +#define GET_SHDSH1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHDSH1) +#define GET_SHNMSH0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0) +#define GET_SHNMSH1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1) +#define GET_NOS0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS0) +#define GET_NOS1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS1) +#define GET_NOS2(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS2) +#define GET_NOS3(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS3) +#define GET_NOS4(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS4) +#define GET_NOS5(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS5) +#define GET_NOS6(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS6) +#define GET_NOS7(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS7) + + +/* RESUME */ +#define GET_TNR(b, c) GET_CONTEXT_FIELD(b, c, RESUME, TNR) + + +/* SCTLR */ +#define GET_M(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, M) +#define GET_TRE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, TRE) +#define GET_AFE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, AFE) +#define GET_HAF(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, HAF) +#define GET_BE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, BE) +#define GET_AFFD(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, AFFD) + + +/* TLBLKCR */ +#define GET_LKE(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, LKE) +#define GET_TLBLCKR_TLBIALLCFG(b, c) \ + GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG) +#define GET_TLBIASIDCFG(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG) +#define GET_TLBIVAACFG(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG) +#define GET_FLOOR(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR) +#define GET_VICTIM(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM) + + +/* TTBCR */ +#define GET_N(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, N) +#define GET_PD0(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, PD0) +#define GET_PD1(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, PD1) + + +/* TTBR0 */ +#define GET_TTBR0_IRGNH(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH) +#define GET_TTBR0_SH(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH) +#define GET_TTBR0_ORGN(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN) +#define GET_TTBR0_NOS(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS) +#define GET_TTBR0_IRGNL(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL) +#define GET_TTBR0_PA(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA) + + +/* TTBR1 */ +#define GET_TTBR1_IRGNH(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH) +#define GET_TTBR1_SH(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH) +#define GET_TTBR1_ORGN(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN) +#define GET_TTBR1_NOS(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS) +#define GET_TTBR1_IRGNL(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL) +#define GET_TTBR1_PA(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA) + + +/* V2PSR */ +#define GET_HIT(b, c) GET_CONTEXT_FIELD(b, c, V2PSR, HIT) +#define GET_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PSR, INDEX) + + +/* V2Pxx UW UR PW PR */ +#define GET_V2PUW_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX) +#define GET_V2PUW_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA) + +#define GET_V2PUR_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX) +#define GET_V2PUR_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA) + +#define GET_V2PPW_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX) +#define GET_V2PPW_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA) + +#define GET_V2PPR_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX) +#define GET_V2PPR_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA) + + +/* Global Registers */ +#define M2VCBR_N (0xFF000) +#define CBACR_N (0xFF800) +#define TLBRSW (0xFFE00) +#define TLBTR0 (0xFFE80) +#define TLBTR1 (0xFFE84) +#define TLBTR2 (0xFFE88) +#define TESTBUSCR (0xFFE8C) +#define GLOBAL_TLBIALL (0xFFF00) +#define TLBIVMID (0xFFF04) +#define CR (0xFFF80) +#define EAR (0xFFF84) +#define ESR (0xFFF88) +#define ESRRESTORE (0xFFF8C) +#define ESYNR0 (0xFFF90) +#define ESYNR1 (0xFFF94) +#define REV (0xFFFF4) +#define IDR (0xFFFF8) +#define RPU_ACR (0xFFFFC) + + +/* Context Bank Registers */ +#define SCTLR (0x000) +#define ACTLR (0x004) +#define CONTEXTIDR (0x008) +#define TTBR0 (0x010) +#define TTBR1 (0x014) +#define TTBCR (0x018) +#define PAR (0x01C) +#define FSR (0x020) +#define FSRRESTORE (0x024) +#define FAR (0x028) +#define FSYNR0 (0x02C) +#define FSYNR1 (0x030) +#define PRRR (0x034) +#define NMRR (0x038) +#define TLBLCKR (0x03C) +#define V2PSR (0x040) +#define TLBFLPTER (0x044) +#define TLBSLPTER (0x048) +#define BFBCR (0x04C) +#define CTX_TLBIALL (0x800) +#define TLBIASID (0x804) +#define TLBIVA (0x808) +#define TLBIVAA (0x80C) +#define V2PPR (0x810) +#define V2PPW (0x814) +#define V2PUR (0x818) +#define V2PUW (0x81C) +#define RESUME (0x820) + + +/* Global Register Fields */ +/* CBACRn */ +#define RWVMID (RWVMID_MASK << RWVMID_SHIFT) +#define RWE (RWE_MASK << RWE_SHIFT) +#define RWGE (RWGE_MASK << RWGE_SHIFT) +#define CBVMID (CBVMID_MASK << CBVMID_SHIFT) +#define IRPTNDX (IRPTNDX_MASK << IRPTNDX_SHIFT) + + +/* CR */ +#define RPUE (RPUE_MASK << RPUE_SHIFT) +#define RPUERE (RPUERE_MASK << RPUERE_SHIFT) +#define RPUEIE (RPUEIE_MASK << RPUEIE_SHIFT) +#define DCDEE (DCDEE_MASK << DCDEE_SHIFT) +#define CLIENTPD (CLIENTPD_MASK << CLIENTPD_SHIFT) +#define STALLD (STALLD_MASK << STALLD_SHIFT) +#define TLBLKCRWE (TLBLKCRWE_MASK << TLBLKCRWE_SHIFT) +#define CR_TLBIALLCFG (CR_TLBIALLCFG_MASK << CR_TLBIALLCFG_SHIFT) +#define TLBIVMIDCFG (TLBIVMIDCFG_MASK << TLBIVMIDCFG_SHIFT) +#define CR_HUME (CR_HUME_MASK << CR_HUME_SHIFT) + + +/* ESR */ +#define CFG (CFG_MASK << CFG_SHIFT) +#define BYPASS (BYPASS_MASK << BYPASS_SHIFT) +#define ESR_MULTI (ESR_MULTI_MASK << ESR_MULTI_SHIFT) + + +/* ESYNR0 */ +#define ESYNR0_AMID (ESYNR0_AMID_MASK << ESYNR0_AMID_SHIFT) +#define ESYNR0_APID (ESYNR0_APID_MASK << ESYNR0_APID_SHIFT) +#define ESYNR0_ABID (ESYNR0_ABID_MASK << ESYNR0_ABID_SHIFT) +#define ESYNR0_AVMID (ESYNR0_AVMID_MASK << ESYNR0_AVMID_SHIFT) +#define ESYNR0_ATID (ESYNR0_ATID_MASK << ESYNR0_ATID_SHIFT) + + +/* ESYNR1 */ +#define ESYNR1_AMEMTYPE (ESYNR1_AMEMTYPE_MASK << ESYNR1_AMEMTYPE_SHIFT) +#define ESYNR1_ASHARED (ESYNR1_ASHARED_MASK << ESYNR1_ASHARED_SHIFT) +#define ESYNR1_AINNERSHARED (ESYNR1_AINNERSHARED_MASK<< \ + ESYNR1_AINNERSHARED_SHIFT) +#define ESYNR1_APRIV (ESYNR1_APRIV_MASK << ESYNR1_APRIV_SHIFT) +#define ESYNR1_APROTNS (ESYNR1_APROTNS_MASK << ESYNR1_APROTNS_SHIFT) +#define ESYNR1_AINST (ESYNR1_AINST_MASK << ESYNR1_AINST_SHIFT) +#define ESYNR1_AWRITE (ESYNR1_AWRITE_MASK << ESYNR1_AWRITE_SHIFT) +#define ESYNR1_ABURST (ESYNR1_ABURST_MASK << ESYNR1_ABURST_SHIFT) +#define ESYNR1_ALEN (ESYNR1_ALEN_MASK << ESYNR1_ALEN_SHIFT) +#define ESYNR1_ASIZE (ESYNR1_ASIZE_MASK << ESYNR1_ASIZE_SHIFT) +#define ESYNR1_ALOCK (ESYNR1_ALOCK_MASK << ESYNR1_ALOCK_SHIFT) +#define ESYNR1_AOOO (ESYNR1_AOOO_MASK << ESYNR1_AOOO_SHIFT) +#define ESYNR1_AFULL (ESYNR1_AFULL_MASK << ESYNR1_AFULL_SHIFT) +#define ESYNR1_AC (ESYNR1_AC_MASK << ESYNR1_AC_SHIFT) +#define ESYNR1_DCD (ESYNR1_DCD_MASK << ESYNR1_DCD_SHIFT) + + +/* IDR */ +#define NM2VCBMT (NM2VCBMT_MASK << NM2VCBMT_SHIFT) +#define HTW (HTW_MASK << HTW_SHIFT) +#define HUM (HUM_MASK << HUM_SHIFT) +#define TLBSIZE (TLBSIZE_MASK << TLBSIZE_SHIFT) +#define NCB (NCB_MASK << NCB_SHIFT) +#define NIRPT (NIRPT_MASK << NIRPT_SHIFT) + + +/* M2VCBRn */ +#define VMID (VMID_MASK << VMID_SHIFT) +#define CBNDX (CBNDX_MASK << CBNDX_SHIFT) +#define BYPASSD (BYPASSD_MASK << BYPASSD_SHIFT) +#define BPRCOSH (BPRCOSH_MASK << BPRCOSH_SHIFT) +#define BPRCISH (BPRCISH_MASK << BPRCISH_SHIFT) +#define BPRCNSH (BPRCNSH_MASK << BPRCNSH_SHIFT) +#define BPSHCFG (BPSHCFG_MASK << BPSHCFG_SHIFT) +#define NSCFG (NSCFG_MASK << NSCFG_SHIFT) +#define BPMTCFG (BPMTCFG_MASK << BPMTCFG_SHIFT) +#define BPMEMTYPE (BPMEMTYPE_MASK << BPMEMTYPE_SHIFT) + + +/* REV */ +#define IDR_MINOR (MINOR_MASK << MINOR_SHIFT) +#define IDR_MAJOR (MAJOR_MASK << MAJOR_SHIFT) + + +/* TESTBUSCR */ +#define TBE (TBE_MASK << TBE_SHIFT) +#define SPDMBE (SPDMBE_MASK << SPDMBE_SHIFT) +#define WGSEL (WGSEL_MASK << WGSEL_SHIFT) +#define TBLSEL (TBLSEL_MASK << TBLSEL_SHIFT) +#define TBHSEL (TBHSEL_MASK << TBHSEL_SHIFT) +#define SPDM0SEL (SPDM0SEL_MASK << SPDM0SEL_SHIFT) +#define SPDM1SEL (SPDM1SEL_MASK << SPDM1SEL_SHIFT) +#define SPDM2SEL (SPDM2SEL_MASK << SPDM2SEL_SHIFT) +#define SPDM3SEL (SPDM3SEL_MASK << SPDM3SEL_SHIFT) + + +/* TLBIVMID */ +#define TLBIVMID_VMID (TLBIVMID_VMID_MASK << TLBIVMID_VMID_SHIFT) + + +/* TLBRSW */ +#define TLBRSW_INDEX (TLBRSW_INDEX_MASK << TLBRSW_INDEX_SHIFT) +#define TLBBFBS (TLBBFBS_MASK << TLBBFBS_SHIFT) + + +/* TLBTR0 */ +#define PR (PR_MASK << PR_SHIFT) +#define PW (PW_MASK << PW_SHIFT) +#define UR (UR_MASK << UR_SHIFT) +#define UW (UW_MASK << UW_SHIFT) +#define XN (XN_MASK << XN_SHIFT) +#define NSDESC (NSDESC_MASK << NSDESC_SHIFT) +#define ISH (ISH_MASK << ISH_SHIFT) +#define SH (SH_MASK << SH_SHIFT) +#define MT (MT_MASK << MT_SHIFT) +#define DPSIZR (DPSIZR_MASK << DPSIZR_SHIFT) +#define DPSIZC (DPSIZC_MASK << DPSIZC_SHIFT) + + +/* TLBTR1 */ +#define TLBTR1_VMID (TLBTR1_VMID_MASK << TLBTR1_VMID_SHIFT) +#define TLBTR1_PA (TLBTR1_PA_MASK << TLBTR1_PA_SHIFT) + + +/* TLBTR2 */ +#define TLBTR2_ASID (TLBTR2_ASID_MASK << TLBTR2_ASID_SHIFT) +#define TLBTR2_V (TLBTR2_V_MASK << TLBTR2_V_SHIFT) +#define TLBTR2_NSTID (TLBTR2_NSTID_MASK << TLBTR2_NSTID_SHIFT) +#define TLBTR2_NV (TLBTR2_NV_MASK << TLBTR2_NV_SHIFT) +#define TLBTR2_VA (TLBTR2_VA_MASK << TLBTR2_VA_SHIFT) + + +/* Context Register Fields */ +/* ACTLR */ +#define CFERE (CFERE_MASK << CFERE_SHIFT) +#define CFEIE (CFEIE_MASK << CFEIE_SHIFT) +#define PTSHCFG (PTSHCFG_MASK << PTSHCFG_SHIFT) +#define RCOSH (RCOSH_MASK << RCOSH_SHIFT) +#define RCISH (RCISH_MASK << RCISH_SHIFT) +#define RCNSH (RCNSH_MASK << RCNSH_SHIFT) +#define PRIVCFG (PRIVCFG_MASK << PRIVCFG_SHIFT) +#define DNA (DNA_MASK << DNA_SHIFT) +#define DNLV2PA (DNLV2PA_MASK << DNLV2PA_SHIFT) +#define TLBMCFG (TLBMCFG_MASK << TLBMCFG_SHIFT) +#define CFCFG (CFCFG_MASK << CFCFG_SHIFT) +#define TIPCF (TIPCF_MASK << TIPCF_SHIFT) +#define V2PCFG (V2PCFG_MASK << V2PCFG_SHIFT) +#define HUME (HUME_MASK << HUME_SHIFT) +#define PTMTCFG (PTMTCFG_MASK << PTMTCFG_SHIFT) +#define PTMEMTYPE (PTMEMTYPE_MASK << PTMEMTYPE_SHIFT) + + +/* BFBCR */ +#define BFBDFE (BFBDFE_MASK << BFBDFE_SHIFT) +#define BFBSFE (BFBSFE_MASK << BFBSFE_SHIFT) +#define SFVS (SFVS_MASK << SFVS_SHIFT) +#define FLVIC (FLVIC_MASK << FLVIC_SHIFT) +#define SLVIC (SLVIC_MASK << SLVIC_SHIFT) + + +/* CONTEXTIDR */ +#define CONTEXTIDR_ASID (CONTEXTIDR_ASID_MASK << CONTEXTIDR_ASID_SHIFT) +#define PROCID (PROCID_MASK << PROCID_SHIFT) + + +/* FSR */ +#define TF (TF_MASK << TF_SHIFT) +#define AFF (AFF_MASK << AFF_SHIFT) +#define APF (APF_MASK << APF_SHIFT) +#define TLBMF (TLBMF_MASK << TLBMF_SHIFT) +#define HTWDEEF (HTWDEEF_MASK << HTWDEEF_SHIFT) +#define HTWSEEF (HTWSEEF_MASK << HTWSEEF_SHIFT) +#define MHF (MHF_MASK << MHF_SHIFT) +#define SL (SL_MASK << SL_SHIFT) +#define SS (SS_MASK << SS_SHIFT) +#define MULTI (MULTI_MASK << MULTI_SHIFT) + + +/* FSYNR0 */ +#define AMID (AMID_MASK << AMID_SHIFT) +#define APID (APID_MASK << APID_SHIFT) +#define ABID (ABID_MASK << ABID_SHIFT) +#define ATID (ATID_MASK << ATID_SHIFT) + + +/* FSYNR1 */ +#define AMEMTYPE (AMEMTYPE_MASK << AMEMTYPE_SHIFT) +#define ASHARED (ASHARED_MASK << ASHARED_SHIFT) +#define AINNERSHARED (AINNERSHARED_MASK << AINNERSHARED_SHIFT) +#define APRIV (APRIV_MASK << APRIV_SHIFT) +#define APROTNS (APROTNS_MASK << APROTNS_SHIFT) +#define AINST (AINST_MASK << AINST_SHIFT) +#define AWRITE (AWRITE_MASK << AWRITE_SHIFT) +#define ABURST (ABURST_MASK << ABURST_SHIFT) +#define ALEN (ALEN_MASK << ALEN_SHIFT) +#define FSYNR1_ASIZE (FSYNR1_ASIZE_MASK << FSYNR1_ASIZE_SHIFT) +#define ALOCK (ALOCK_MASK << ALOCK_SHIFT) +#define AFULL (AFULL_MASK << AFULL_SHIFT) + + +/* NMRR */ +#define ICPC0 (ICPC0_MASK << ICPC0_SHIFT) +#define ICPC1 (ICPC1_MASK << ICPC1_SHIFT) +#define ICPC2 (ICPC2_MASK << ICPC2_SHIFT) +#define ICPC3 (ICPC3_MASK << ICPC3_SHIFT) +#define ICPC4 (ICPC4_MASK << ICPC4_SHIFT) +#define ICPC5 (ICPC5_MASK << ICPC5_SHIFT) +#define ICPC6 (ICPC6_MASK << ICPC6_SHIFT) +#define ICPC7 (ICPC7_MASK << ICPC7_SHIFT) +#define OCPC0 (OCPC0_MASK << OCPC0_SHIFT) +#define OCPC1 (OCPC1_MASK << OCPC1_SHIFT) +#define OCPC2 (OCPC2_MASK << OCPC2_SHIFT) +#define OCPC3 (OCPC3_MASK << OCPC3_SHIFT) +#define OCPC4 (OCPC4_MASK << OCPC4_SHIFT) +#define OCPC5 (OCPC5_MASK << OCPC5_SHIFT) +#define OCPC6 (OCPC6_MASK << OCPC6_SHIFT) +#define OCPC7 (OCPC7_MASK << OCPC7_SHIFT) + + +/* PAR */ +#define FAULT (FAULT_MASK << FAULT_SHIFT) +/* If a fault is present, these are the +same as the fault fields in the FAR */ +#define FAULT_TF (FAULT_TF_MASK << FAULT_TF_SHIFT) +#define FAULT_AFF (FAULT_AFF_MASK << FAULT_AFF_SHIFT) +#define FAULT_APF (FAULT_APF_MASK << FAULT_APF_SHIFT) +#define FAULT_TLBMF (FAULT_TLBMF_MASK << FAULT_TLBMF_SHIFT) +#define FAULT_HTWDEEF (FAULT_HTWDEEF_MASK << FAULT_HTWDEEF_SHIFT) +#define FAULT_HTWSEEF (FAULT_HTWSEEF_MASK << FAULT_HTWSEEF_SHIFT) +#define FAULT_MHF (FAULT_MHF_MASK << FAULT_MHF_SHIFT) +#define FAULT_SL (FAULT_SL_MASK << FAULT_SL_SHIFT) +#define FAULT_SS (FAULT_SS_MASK << FAULT_SS_SHIFT) + +/* If NO fault is present, the following fields are in effect */ +/* (FAULT remains as before) */ +#define PAR_NOFAULT_SS (PAR_NOFAULT_SS_MASK << PAR_NOFAULT_SS_SHIFT) +#define PAR_NOFAULT_MT (PAR_NOFAULT_MT_MASK << PAR_NOFAULT_MT_SHIFT) +#define PAR_NOFAULT_SH (PAR_NOFAULT_SH_MASK << PAR_NOFAULT_SH_SHIFT) +#define PAR_NOFAULT_NS (PAR_NOFAULT_NS_MASK << PAR_NOFAULT_NS_SHIFT) +#define PAR_NOFAULT_NOS (PAR_NOFAULT_NOS_MASK << PAR_NOFAULT_NOS_SHIFT) +#define PAR_NPFAULT_PA (PAR_NPFAULT_PA_MASK << PAR_NPFAULT_PA_SHIFT) + + +/* PRRR */ +#define MTC0 (MTC0_MASK << MTC0_SHIFT) +#define MTC1 (MTC1_MASK << MTC1_SHIFT) +#define MTC2 (MTC2_MASK << MTC2_SHIFT) +#define MTC3 (MTC3_MASK << MTC3_SHIFT) +#define MTC4 (MTC4_MASK << MTC4_SHIFT) +#define MTC5 (MTC5_MASK << MTC5_SHIFT) +#define MTC6 (MTC6_MASK << MTC6_SHIFT) +#define MTC7 (MTC7_MASK << MTC7_SHIFT) +#define SHDSH0 (SHDSH0_MASK << SHDSH0_SHIFT) +#define SHDSH1 (SHDSH1_MASK << SHDSH1_SHIFT) +#define SHNMSH0 (SHNMSH0_MASK << SHNMSH0_SHIFT) +#define SHNMSH1 (SHNMSH1_MASK << SHNMSH1_SHIFT) +#define NOS0 (NOS0_MASK << NOS0_SHIFT) +#define NOS1 (NOS1_MASK << NOS1_SHIFT) +#define NOS2 (NOS2_MASK << NOS2_SHIFT) +#define NOS3 (NOS3_MASK << NOS3_SHIFT) +#define NOS4 (NOS4_MASK << NOS4_SHIFT) +#define NOS5 (NOS5_MASK << NOS5_SHIFT) +#define NOS6 (NOS6_MASK << NOS6_SHIFT) +#define NOS7 (NOS7_MASK << NOS7_SHIFT) + + +/* RESUME */ +#define TNR (TNR_MASK << TNR_SHIFT) + + +/* SCTLR */ +#define M (M_MASK << M_SHIFT) +#define TRE (TRE_MASK << TRE_SHIFT) +#define AFE (AFE_MASK << AFE_SHIFT) +#define HAF (HAF_MASK << HAF_SHIFT) +#define BE (BE_MASK << BE_SHIFT) +#define AFFD (AFFD_MASK << AFFD_SHIFT) + + +/* TLBIASID */ +#define TLBIASID_ASID (TLBIASID_ASID_MASK << TLBIASID_ASID_SHIFT) + + +/* TLBIVA */ +#define TLBIVA_ASID (TLBIVA_ASID_MASK << TLBIVA_ASID_SHIFT) +#define TLBIVA_VA (TLBIVA_VA_MASK << TLBIVA_VA_SHIFT) + + +/* TLBIVAA */ +#define TLBIVAA_VA (TLBIVAA_VA_MASK << TLBIVAA_VA_SHIFT) + + +/* TLBLCKR */ +#define LKE (LKE_MASK << LKE_SHIFT) +#define TLBLCKR_TLBIALLCFG (TLBLCKR_TLBIALLCFG_MASK<<TLBLCKR_TLBIALLCFG_SHIFT) +#define TLBIASIDCFG (TLBIASIDCFG_MASK << TLBIASIDCFG_SHIFT) +#define TLBIVAACFG (TLBIVAACFG_MASK << TLBIVAACFG_SHIFT) +#define FLOOR (FLOOR_MASK << FLOOR_SHIFT) +#define VICTIM (VICTIM_MASK << VICTIM_SHIFT) + + +/* TTBCR */ +#define N (N_MASK << N_SHIFT) +#define PD0 (PD0_MASK << PD0_SHIFT) +#define PD1 (PD1_MASK << PD1_SHIFT) + + +/* TTBR0 */ +#define TTBR0_IRGNH (TTBR0_IRGNH_MASK << TTBR0_IRGNH_SHIFT) +#define TTBR0_SH (TTBR0_SH_MASK << TTBR0_SH_SHIFT) +#define TTBR0_ORGN (TTBR0_ORGN_MASK << TTBR0_ORGN_SHIFT) +#define TTBR0_NOS (TTBR0_NOS_MASK << TTBR0_NOS_SHIFT) +#define TTBR0_IRGNL (TTBR0_IRGNL_MASK << TTBR0_IRGNL_SHIFT) +#define TTBR0_PA (TTBR0_PA_MASK << TTBR0_PA_SHIFT) + + +/* TTBR1 */ +#define TTBR1_IRGNH (TTBR1_IRGNH_MASK << TTBR1_IRGNH_SHIFT) +#define TTBR1_SH (TTBR1_SH_MASK << TTBR1_SH_SHIFT) +#define TTBR1_ORGN (TTBR1_ORGN_MASK << TTBR1_ORGN_SHIFT) +#define TTBR1_NOS (TTBR1_NOS_MASK << TTBR1_NOS_SHIFT) +#define TTBR1_IRGNL (TTBR1_IRGNL_MASK << TTBR1_IRGNL_SHIFT) +#define TTBR1_PA (TTBR1_PA_MASK << TTBR1_PA_SHIFT) + + +/* V2PSR */ +#define HIT (HIT_MASK << HIT_SHIFT) +#define INDEX (INDEX_MASK << INDEX_SHIFT) + + +/* V2Pxx */ +#define V2Pxx_INDEX (V2Pxx_INDEX_MASK << V2Pxx_INDEX_SHIFT) +#define V2Pxx_VA (V2Pxx_VA_MASK << V2Pxx_VA_SHIFT) + + +/* Global Register Masks */ +/* CBACRn */ +#define RWVMID_MASK 0x1F +#define RWE_MASK 0x01 +#define RWGE_MASK 0x01 +#define CBVMID_MASK 0x1F +#define IRPTNDX_MASK 0xFF + + +/* CR */ +#define RPUE_MASK 0x01 +#define RPUERE_MASK 0x01 +#define RPUEIE_MASK 0x01 +#define DCDEE_MASK 0x01 +#define CLIENTPD_MASK 0x01 +#define STALLD_MASK 0x01 +#define TLBLKCRWE_MASK 0x01 +#define CR_TLBIALLCFG_MASK 0x01 +#define TLBIVMIDCFG_MASK 0x01 +#define CR_HUME_MASK 0x01 + + +/* ESR */ +#define CFG_MASK 0x01 +#define BYPASS_MASK 0x01 +#define ESR_MULTI_MASK 0x01 + + +/* ESYNR0 */ +#define ESYNR0_AMID_MASK 0xFF +#define ESYNR0_APID_MASK 0x1F +#define ESYNR0_ABID_MASK 0x07 +#define ESYNR0_AVMID_MASK 0x1F +#define ESYNR0_ATID_MASK 0xFF + + +/* ESYNR1 */ +#define ESYNR1_AMEMTYPE_MASK 0x07 +#define ESYNR1_ASHARED_MASK 0x01 +#define ESYNR1_AINNERSHARED_MASK 0x01 +#define ESYNR1_APRIV_MASK 0x01 +#define ESYNR1_APROTNS_MASK 0x01 +#define ESYNR1_AINST_MASK 0x01 +#define ESYNR1_AWRITE_MASK 0x01 +#define ESYNR1_ABURST_MASK 0x01 +#define ESYNR1_ALEN_MASK 0x0F +#define ESYNR1_ASIZE_MASK 0x01 +#define ESYNR1_ALOCK_MASK 0x03 +#define ESYNR1_AOOO_MASK 0x01 +#define ESYNR1_AFULL_MASK 0x01 +#define ESYNR1_AC_MASK 0x01 +#define ESYNR1_DCD_MASK 0x01 + + +/* IDR */ +#define NM2VCBMT_MASK 0x1FF +#define HTW_MASK 0x01 +#define HUM_MASK 0x01 +#define TLBSIZE_MASK 0x0F +#define NCB_MASK 0xFF +#define NIRPT_MASK 0xFF + + +/* M2VCBRn */ +#define VMID_MASK 0x1F +#define CBNDX_MASK 0xFF +#define BYPASSD_MASK 0x01 +#define BPRCOSH_MASK 0x01 +#define BPRCISH_MASK 0x01 +#define BPRCNSH_MASK 0x01 +#define BPSHCFG_MASK 0x03 +#define NSCFG_MASK 0x03 +#define BPMTCFG_MASK 0x01 +#define BPMEMTYPE_MASK 0x07 + + +/* REV */ +#define MINOR_MASK 0x0F +#define MAJOR_MASK 0x0F + + +/* TESTBUSCR */ +#define TBE_MASK 0x01 +#define SPDMBE_MASK 0x01 +#define WGSEL_MASK 0x03 +#define TBLSEL_MASK 0x03 +#define TBHSEL_MASK 0x03 +#define SPDM0SEL_MASK 0x0F +#define SPDM1SEL_MASK 0x0F +#define SPDM2SEL_MASK 0x0F +#define SPDM3SEL_MASK 0x0F + + +/* TLBIMID */ +#define TLBIVMID_VMID_MASK 0x1F + + +/* TLBRSW */ +#define TLBRSW_INDEX_MASK 0xFF +#define TLBBFBS_MASK 0x03 + + +/* TLBTR0 */ +#define PR_MASK 0x01 +#define PW_MASK 0x01 +#define UR_MASK 0x01 +#define UW_MASK 0x01 +#define XN_MASK 0x01 +#define NSDESC_MASK 0x01 +#define ISH_MASK 0x01 +#define SH_MASK 0x01 +#define MT_MASK 0x07 +#define DPSIZR_MASK 0x07 +#define DPSIZC_MASK 0x07 + + +/* TLBTR1 */ +#define TLBTR1_VMID_MASK 0x1F +#define TLBTR1_PA_MASK 0x000FFFFF + + +/* TLBTR2 */ +#define TLBTR2_ASID_MASK 0xFF +#define TLBTR2_V_MASK 0x01 +#define TLBTR2_NSTID_MASK 0x01 +#define TLBTR2_NV_MASK 0x01 +#define TLBTR2_VA_MASK 0x000FFFFF + + +/* Global Register Shifts */ +/* CBACRn */ +#define RWVMID_SHIFT 0 +#define RWE_SHIFT 8 +#define RWGE_SHIFT 9 +#define CBVMID_SHIFT 16 +#define IRPTNDX_SHIFT 24 + + +/* CR */ +#define RPUE_SHIFT 0 +#define RPUERE_SHIFT 1 +#define RPUEIE_SHIFT 2 +#define DCDEE_SHIFT 3 +#define CLIENTPD_SHIFT 4 +#define STALLD_SHIFT 5 +#define TLBLKCRWE_SHIFT 6 +#define CR_TLBIALLCFG_SHIFT 7 +#define TLBIVMIDCFG_SHIFT 8 +#define CR_HUME_SHIFT 9 + + +/* ESR */ +#define CFG_SHIFT 0 +#define BYPASS_SHIFT 1 +#define ESR_MULTI_SHIFT 31 + + +/* ESYNR0 */ +#define ESYNR0_AMID_SHIFT 0 +#define ESYNR0_APID_SHIFT 8 +#define ESYNR0_ABID_SHIFT 13 +#define ESYNR0_AVMID_SHIFT 16 +#define ESYNR0_ATID_SHIFT 24 + + +/* ESYNR1 */ +#define ESYNR1_AMEMTYPE_SHIFT 0 +#define ESYNR1_ASHARED_SHIFT 3 +#define ESYNR1_AINNERSHARED_SHIFT 4 +#define ESYNR1_APRIV_SHIFT 5 +#define ESYNR1_APROTNS_SHIFT 6 +#define ESYNR1_AINST_SHIFT 7 +#define ESYNR1_AWRITE_SHIFT 8 +#define ESYNR1_ABURST_SHIFT 10 +#define ESYNR1_ALEN_SHIFT 12 +#define ESYNR1_ASIZE_SHIFT 16 +#define ESYNR1_ALOCK_SHIFT 20 +#define ESYNR1_AOOO_SHIFT 22 +#define ESYNR1_AFULL_SHIFT 24 +#define ESYNR1_AC_SHIFT 30 +#define ESYNR1_DCD_SHIFT 31 + + +/* IDR */ +#define NM2VCBMT_SHIFT 0 +#define HTW_SHIFT 9 +#define HUM_SHIFT 10 +#define TLBSIZE_SHIFT 12 +#define NCB_SHIFT 16 +#define NIRPT_SHIFT 24 + + +/* M2VCBRn */ +#define VMID_SHIFT 0 +#define CBNDX_SHIFT 8 +#define BYPASSD_SHIFT 16 +#define BPRCOSH_SHIFT 17 +#define BPRCISH_SHIFT 18 +#define BPRCNSH_SHIFT 19 +#define BPSHCFG_SHIFT 20 +#define NSCFG_SHIFT 22 +#define BPMTCFG_SHIFT 24 +#define BPMEMTYPE_SHIFT 25 + + +/* REV */ +#define MINOR_SHIFT 0 +#define MAJOR_SHIFT 4 + + +/* TESTBUSCR */ +#define TBE_SHIFT 0 +#define SPDMBE_SHIFT 1 +#define WGSEL_SHIFT 8 +#define TBLSEL_SHIFT 12 +#define TBHSEL_SHIFT 14 +#define SPDM0SEL_SHIFT 16 +#define SPDM1SEL_SHIFT 20 +#define SPDM2SEL_SHIFT 24 +#define SPDM3SEL_SHIFT 28 + + +/* TLBIMID */ +#define TLBIVMID_VMID_SHIFT 0 + + +/* TLBRSW */ +#define TLBRSW_INDEX_SHIFT 0 +#define TLBBFBS_SHIFT 8 + + +/* TLBTR0 */ +#define PR_SHIFT 0 +#define PW_SHIFT 1 +#define UR_SHIFT 2 +#define UW_SHIFT 3 +#define XN_SHIFT 4 +#define NSDESC_SHIFT 6 +#define ISH_SHIFT 7 +#define SH_SHIFT 8 +#define MT_SHIFT 9 +#define DPSIZR_SHIFT 16 +#define DPSIZC_SHIFT 20 + + +/* TLBTR1 */ +#define TLBTR1_VMID_SHIFT 0 +#define TLBTR1_PA_SHIFT 12 + + +/* TLBTR2 */ +#define TLBTR2_ASID_SHIFT 0 +#define TLBTR2_V_SHIFT 8 +#define TLBTR2_NSTID_SHIFT 9 +#define TLBTR2_NV_SHIFT 10 +#define TLBTR2_VA_SHIFT 12 + + +/* Context Register Masks */ +/* ACTLR */ +#define CFERE_MASK 0x01 +#define CFEIE_MASK 0x01 +#define PTSHCFG_MASK 0x03 +#define RCOSH_MASK 0x01 +#define RCISH_MASK 0x01 +#define RCNSH_MASK 0x01 +#define PRIVCFG_MASK 0x03 +#define DNA_MASK 0x01 +#define DNLV2PA_MASK 0x01 +#define TLBMCFG_MASK 0x03 +#define CFCFG_MASK 0x01 +#define TIPCF_MASK 0x01 +#define V2PCFG_MASK 0x03 +#define HUME_MASK 0x01 +#define PTMTCFG_MASK 0x01 +#define PTMEMTYPE_MASK 0x07 + + +/* BFBCR */ +#define BFBDFE_MASK 0x01 +#define BFBSFE_MASK 0x01 +#define SFVS_MASK 0x01 +#define FLVIC_MASK 0x0F +#define SLVIC_MASK 0x0F + + +/* CONTEXTIDR */ +#define CONTEXTIDR_ASID_MASK 0xFF +#define PROCID_MASK 0x00FFFFFF + + +/* FSR */ +#define TF_MASK 0x01 +#define AFF_MASK 0x01 +#define APF_MASK 0x01 +#define TLBMF_MASK 0x01 +#define HTWDEEF_MASK 0x01 +#define HTWSEEF_MASK 0x01 +#define MHF_MASK 0x01 +#define SL_MASK 0x01 +#define SS_MASK 0x01 +#define MULTI_MASK 0x01 + + +/* FSYNR0 */ +#define AMID_MASK 0xFF +#define APID_MASK 0x1F +#define ABID_MASK 0x07 +#define ATID_MASK 0xFF + + +/* FSYNR1 */ +#define AMEMTYPE_MASK 0x07 +#define ASHARED_MASK 0x01 +#define AINNERSHARED_MASK 0x01 +#define APRIV_MASK 0x01 +#define APROTNS_MASK 0x01 +#define AINST_MASK 0x01 +#define AWRITE_MASK 0x01 +#define ABURST_MASK 0x01 +#define ALEN_MASK 0x0F +#define FSYNR1_ASIZE_MASK 0x07 +#define ALOCK_MASK 0x03 +#define AFULL_MASK 0x01 + + +/* NMRR */ +#define ICPC0_MASK 0x03 +#define ICPC1_MASK 0x03 +#define ICPC2_MASK 0x03 +#define ICPC3_MASK 0x03 +#define ICPC4_MASK 0x03 +#define ICPC5_MASK 0x03 +#define ICPC6_MASK 0x03 +#define ICPC7_MASK 0x03 +#define OCPC0_MASK 0x03 +#define OCPC1_MASK 0x03 +#define OCPC2_MASK 0x03 +#define OCPC3_MASK 0x03 +#define OCPC4_MASK 0x03 +#define OCPC5_MASK 0x03 +#define OCPC6_MASK 0x03 +#define OCPC7_MASK 0x03 + + +/* PAR */ +#define FAULT_MASK 0x01 +/* If a fault is present, these are the +same as the fault fields in the FAR */ +#define FAULT_TF_MASK 0x01 +#define FAULT_AFF_MASK 0x01 +#define FAULT_APF_MASK 0x01 +#define FAULT_TLBMF_MASK 0x01 +#define FAULT_HTWDEEF_MASK 0x01 +#define FAULT_HTWSEEF_MASK 0x01 +#define FAULT_MHF_MASK 0x01 +#define FAULT_SL_MASK 0x01 +#define FAULT_SS_MASK 0x01 + +/* If NO fault is present, the following + * fields are in effect + * (FAULT remains as before) */ +#define PAR_NOFAULT_SS_MASK 0x01 +#define PAR_NOFAULT_MT_MASK 0x07 +#define PAR_NOFAULT_SH_MASK 0x01 +#define PAR_NOFAULT_NS_MASK 0x01 +#define PAR_NOFAULT_NOS_MASK 0x01 +#define PAR_NPFAULT_PA_MASK 0x000FFFFF + + +/* PRRR */ +#define MTC0_MASK 0x03 +#define MTC1_MASK 0x03 +#define MTC2_MASK 0x03 +#define MTC3_MASK 0x03 +#define MTC4_MASK 0x03 +#define MTC5_MASK 0x03 +#define MTC6_MASK 0x03 +#define MTC7_MASK 0x03 +#define SHDSH0_MASK 0x01 +#define SHDSH1_MASK 0x01 +#define SHNMSH0_MASK 0x01 +#define SHNMSH1_MASK 0x01 +#define NOS0_MASK 0x01 +#define NOS1_MASK 0x01 +#define NOS2_MASK 0x01 +#define NOS3_MASK 0x01 +#define NOS4_MASK 0x01 +#define NOS5_MASK 0x01 +#define NOS6_MASK 0x01 +#define NOS7_MASK 0x01 + + +/* RESUME */ +#define TNR_MASK 0x01 + + +/* SCTLR */ +#define M_MASK 0x01 +#define TRE_MASK 0x01 +#define AFE_MASK 0x01 +#define HAF_MASK 0x01 +#define BE_MASK 0x01 +#define AFFD_MASK 0x01 + + +/* TLBIASID */ +#define TLBIASID_ASID_MASK 0xFF + + +/* TLBIVA */ +#define TLBIVA_ASID_MASK 0xFF +#define TLBIVA_VA_MASK 0x000FFFFF + + +/* TLBIVAA */ +#define TLBIVAA_VA_MASK 0x000FFFFF + + +/* TLBLCKR */ +#define LKE_MASK 0x01 +#define TLBLCKR_TLBIALLCFG_MASK 0x01 +#define TLBIASIDCFG_MASK 0x01 +#define TLBIVAACFG_MASK 0x01 +#define FLOOR_MASK 0xFF +#define VICTIM_MASK 0xFF + + +/* TTBCR */ +#define N_MASK 0x07 +#define PD0_MASK 0x01 +#define PD1_MASK 0x01 + + +/* TTBR0 */ +#define TTBR0_IRGNH_MASK 0x01 +#define TTBR0_SH_MASK 0x01 +#define TTBR0_ORGN_MASK 0x03 +#define TTBR0_NOS_MASK 0x01 +#define TTBR0_IRGNL_MASK 0x01 +#define TTBR0_PA_MASK 0x0003FFFF + + +/* TTBR1 */ +#define TTBR1_IRGNH_MASK 0x01 +#define TTBR1_SH_MASK 0x01 +#define TTBR1_ORGN_MASK 0x03 +#define TTBR1_NOS_MASK 0x01 +#define TTBR1_IRGNL_MASK 0x01 +#define TTBR1_PA_MASK 0x0003FFFF + + +/* V2PSR */ +#define HIT_MASK 0x01 +#define INDEX_MASK 0xFF + + +/* V2Pxx */ +#define V2Pxx_INDEX_MASK 0xFF +#define V2Pxx_VA_MASK 0x000FFFFF + + +/* Context Register Shifts */ +/* ACTLR */ +#define CFERE_SHIFT 0 +#define CFEIE_SHIFT 1 +#define PTSHCFG_SHIFT 2 +#define RCOSH_SHIFT 4 +#define RCISH_SHIFT 5 +#define RCNSH_SHIFT 6 +#define PRIVCFG_SHIFT 8 +#define DNA_SHIFT 10 +#define DNLV2PA_SHIFT 11 +#define TLBMCFG_SHIFT 12 +#define CFCFG_SHIFT 14 +#define TIPCF_SHIFT 15 +#define V2PCFG_SHIFT 16 +#define HUME_SHIFT 18 +#define PTMTCFG_SHIFT 20 +#define PTMEMTYPE_SHIFT 21 + + +/* BFBCR */ +#define BFBDFE_SHIFT 0 +#define BFBSFE_SHIFT 1 +#define SFVS_SHIFT 2 +#define FLVIC_SHIFT 4 +#define SLVIC_SHIFT 8 + + +/* CONTEXTIDR */ +#define CONTEXTIDR_ASID_SHIFT 0 +#define PROCID_SHIFT 8 + + +/* FSR */ +#define TF_SHIFT 1 +#define AFF_SHIFT 2 +#define APF_SHIFT 3 +#define TLBMF_SHIFT 4 +#define HTWDEEF_SHIFT 5 +#define HTWSEEF_SHIFT 6 +#define MHF_SHIFT 7 +#define SL_SHIFT 16 +#define SS_SHIFT 30 +#define MULTI_SHIFT 31 + + +/* FSYNR0 */ +#define AMID_SHIFT 0 +#define APID_SHIFT 8 +#define ABID_SHIFT 13 +#define ATID_SHIFT 24 + + +/* FSYNR1 */ +#define AMEMTYPE_SHIFT 0 +#define ASHARED_SHIFT 3 +#define AINNERSHARED_SHIFT 4 +#define APRIV_SHIFT 5 +#define APROTNS_SHIFT 6 +#define AINST_SHIFT 7 +#define AWRITE_SHIFT 8 +#define ABURST_SHIFT 10 +#define ALEN_SHIFT 12 +#define FSYNR1_ASIZE_SHIFT 16 +#define ALOCK_SHIFT 20 +#define AFULL_SHIFT 24 + + +/* NMRR */ +#define ICPC0_SHIFT 0 +#define ICPC1_SHIFT 2 +#define ICPC2_SHIFT 4 +#define ICPC3_SHIFT 6 +#define ICPC4_SHIFT 8 +#define ICPC5_SHIFT 10 +#define ICPC6_SHIFT 12 +#define ICPC7_SHIFT 14 +#define OCPC0_SHIFT 16 +#define OCPC1_SHIFT 18 +#define OCPC2_SHIFT 20 +#define OCPC3_SHIFT 22 +#define OCPC4_SHIFT 24 +#define OCPC5_SHIFT 26 +#define OCPC6_SHIFT 28 +#define OCPC7_SHIFT 30 + + +/* PAR */ +#define FAULT_SHIFT 0 +/* If a fault is present, these are the +same as the fault fields in the FAR */ +#define FAULT_TF_SHIFT 1 +#define FAULT_AFF_SHIFT 2 +#define FAULT_APF_SHIFT 3 +#define FAULT_TLBMF_SHIFT 4 +#define FAULT_HTWDEEF_SHIFT 5 +#define FAULT_HTWSEEF_SHIFT 6 +#define FAULT_MHF_SHIFT 7 +#define FAULT_SL_SHIFT 16 +#define FAULT_SS_SHIFT 30 + +/* If NO fault is present, the following + * fields are in effect + * (FAULT remains as before) */ +#define PAR_NOFAULT_SS_SHIFT 1 +#define PAR_NOFAULT_MT_SHIFT 4 +#define PAR_NOFAULT_SH_SHIFT 7 +#define PAR_NOFAULT_NS_SHIFT 9 +#define PAR_NOFAULT_NOS_SHIFT 10 +#define PAR_NPFAULT_PA_SHIFT 12 + + +/* PRRR */ +#define MTC0_SHIFT 0 +#define MTC1_SHIFT 2 +#define MTC2_SHIFT 4 +#define MTC3_SHIFT 6 +#define MTC4_SHIFT 8 +#define MTC5_SHIFT 10 +#define MTC6_SHIFT 12 +#define MTC7_SHIFT 14 +#define SHDSH0_SHIFT 16 +#define SHDSH1_SHIFT 17 +#define SHNMSH0_SHIFT 18 +#define SHNMSH1_SHIFT 19 +#define NOS0_SHIFT 24 +#define NOS1_SHIFT 25 +#define NOS2_SHIFT 26 +#define NOS3_SHIFT 27 +#define NOS4_SHIFT 28 +#define NOS5_SHIFT 29 +#define NOS6_SHIFT 30 +#define NOS7_SHIFT 31 + + +/* RESUME */ +#define TNR_SHIFT 0 + + +/* SCTLR */ +#define M_SHIFT 0 +#define TRE_SHIFT 1 +#define AFE_SHIFT 2 +#define HAF_SHIFT 3 +#define BE_SHIFT 4 +#define AFFD_SHIFT 5 + + +/* TLBIASID */ +#define TLBIASID_ASID_SHIFT 0 + + +/* TLBIVA */ +#define TLBIVA_ASID_SHIFT 0 +#define TLBIVA_VA_SHIFT 12 + + +/* TLBIVAA */ +#define TLBIVAA_VA_SHIFT 12 + + +/* TLBLCKR */ +#define LKE_SHIFT 0 +#define TLBLCKR_TLBIALLCFG_SHIFT 1 +#define TLBIASIDCFG_SHIFT 2 +#define TLBIVAACFG_SHIFT 3 +#define FLOOR_SHIFT 8 +#define VICTIM_SHIFT 8 + + +/* TTBCR */ +#define N_SHIFT 3 +#define PD0_SHIFT 4 +#define PD1_SHIFT 5 + + +/* TTBR0 */ +#define TTBR0_IRGNH_SHIFT 0 +#define TTBR0_SH_SHIFT 1 +#define TTBR0_ORGN_SHIFT 3 +#define TTBR0_NOS_SHIFT 5 +#define TTBR0_IRGNL_SHIFT 6 +#define TTBR0_PA_SHIFT 14 + + +/* TTBR1 */ +#define TTBR1_IRGNH_SHIFT 0 +#define TTBR1_SH_SHIFT 1 +#define TTBR1_ORGN_SHIFT 3 +#define TTBR1_NOS_SHIFT 5 +#define TTBR1_IRGNL_SHIFT 6 +#define TTBR1_PA_SHIFT 14 + + +/* V2PSR */ +#define HIT_SHIFT 0 +#define INDEX_SHIFT 8 + + +/* V2Pxx */ +#define V2Pxx_INDEX_SHIFT 0 +#define V2Pxx_VA_SHIFT 12 + +#endif diff --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h new file mode 100644 index 0000000..36074cf --- /dev/null +++ b/arch/arm/mach-msm/include/mach/irqs-8x60.h @@ -0,0 +1,253 @@ +/* Copyright (c) 2010 Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __ASM_ARCH_MSM_IRQS_8X60_H +#define __ASM_ARCH_MSM_IRQS_8X60_H + +/* MSM ACPU Interrupt Numbers */ + +/* 0-15: STI/SGI (software triggered/generated interrupts) + * 16-31: PPI (private peripheral interrupts) + * 32+: SPI (shared peripheral interrupts) + */ + +#define GIC_PPI_START 16 +#define GIC_SPI_START 32 + +#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 0) +#define INT_GP_TIMER_EXP (GIC_PPI_START + 1) +#define INT_GP_TIMER2_EXP (GIC_PPI_START + 2) +#define WDT0_ACCSCSSNBARK_INT (GIC_PPI_START + 3) +#define WDT1_ACCSCSSNBARK_INT (GIC_PPI_START + 4) +#define AVS_SVICINT (GIC_PPI_START + 5) +#define AVS_SVICINTSWDONE (GIC_PPI_START + 6) +#define CPU_DBGCPUXCOMMRXFULL (GIC_PPI_START + 7) +#define CPU_DBGCPUXCOMMTXEMPTY (GIC_PPI_START + 8) +#define CPU_SICCPUXPERFMONIRPTREQ (GIC_PPI_START + 9) +#define SC_AVSCPUXDOWN (GIC_PPI_START + 10) +#define SC_AVSCPUXUP (GIC_PPI_START + 11) +#define SC_SICCPUXACGIRPTREQ (GIC_PPI_START + 12) +/* PPI 13 to 15 are unused */ + + +#define SC_SICMPUIRPTREQ (GIC_SPI_START + 0) +#define SC_SICL2IRPTREQ (GIC_SPI_START + 1) +#define SC_SICL2ACGIRPTREQ (GIC_SPI_START + 2) +#define NC (GIC_SPI_START + 3) +#define TLMM_SCSS_DIR_CONN_IRQ_0 (GIC_SPI_START + 4) +#define TLMM_SCSS_DIR_CONN_IRQ_1 (GIC_SPI_START + 5) +#define TLMM_SCSS_DIR_CONN_IRQ_2 (GIC_SPI_START + 6) +#define TLMM_SCSS_DIR_CONN_IRQ_3 (GIC_SPI_START + 7) +#define TLMM_SCSS_DIR_CONN_IRQ_4 (GIC_SPI_START + 8) +#define TLMM_SCSS_DIR_CONN_IRQ_5 (GIC_SPI_START + 9) +#define TLMM_SCSS_DIR_CONN_IRQ_6 (GIC_SPI_START + 10) +#define TLMM_SCSS_DIR_CONN_IRQ_7 (GIC_SPI_START + 11) +#define TLMM_SCSS_DIR_CONN_IRQ_8 (GIC_SPI_START + 12) +#define TLMM_SCSS_DIR_CONN_IRQ_9 (GIC_SPI_START + 13) +#define PM8058_SEC_IRQ_N (GIC_SPI_START + 14) +#define PM8901_SEC_IRQ_N (GIC_SPI_START + 15) +#define TLMM_SCSS_SUMMARY_IRQ (GIC_SPI_START + 16) +#define SPDM_RT_1_IRQ (GIC_SPI_START + 17) +#define SPDM_DIAG_IRQ (GIC_SPI_START + 18) +#define RPM_SCSS_CPU0_GP_HIGH_IRQ (GIC_SPI_START + 19) +#define RPM_SCSS_CPU0_GP_MEDIUM_IRQ (GIC_SPI_START + 20) +#define RPM_SCSS_CPU0_GP_LOW_IRQ (GIC_SPI_START + 21) +#define RPM_SCSS_CPU0_WAKE_UP_IRQ (GIC_SPI_START + 22) +#define RPM_SCSS_CPU1_GP_HIGH_IRQ (GIC_SPI_START + 23) +#define RPM_SCSS_CPU1_GP_MEDIUM_IRQ (GIC_SPI_START + 24) +#define RPM_SCSS_CPU1_GP_LOW_IRQ (GIC_SPI_START + 25) +#define RPM_SCSS_CPU1_WAKE_UP_IRQ (GIC_SPI_START + 26) +#define SSBI2_2_SC_CPU0_SECURE_INT (GIC_SPI_START + 27) +#define SSBI2_2_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 28) +#define SSBI2_1_SC_CPU0_SECURE_INT (GIC_SPI_START + 29) +#define SSBI2_1_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 30) +#define MSMC_SC_SEC_CE_IRQ (GIC_SPI_START + 31) +#define MSMC_SC_PRI_CE_IRQ (GIC_SPI_START + 32) +#define MARM_FIQ (GIC_SPI_START + 33) +#define MARM_IRQ (GIC_SPI_START + 34) +#define MARM_L2CC_IRQ (GIC_SPI_START + 35) +#define MARM_WDOG_EXPIRED (GIC_SPI_START + 36) +#define MARM_SCSS_GP_IRQ_0 (GIC_SPI_START + 37) +#define MARM_SCSS_GP_IRQ_1 (GIC_SPI_START + 38) +#define MARM_SCSS_GP_IRQ_2 (GIC_SPI_START + 39) +#define MARM_SCSS_GP_IRQ_3 (GIC_SPI_START + 40) +#define MARM_SCSS_GP_IRQ_4 (GIC_SPI_START + 41) +#define MARM_SCSS_GP_IRQ_5 (GIC_SPI_START + 42) +#define MARM_SCSS_GP_IRQ_6 (GIC_SPI_START + 43) +#define MARM_SCSS_GP_IRQ_7 (GIC_SPI_START + 44) +#define MARM_SCSS_GP_IRQ_8 (GIC_SPI_START + 45) +#define MARM_SCSS_GP_IRQ_9 (GIC_SPI_START + 46) +#define VPE_IRQ (GIC_SPI_START + 47) +#define VFE_IRQ (GIC_SPI_START + 48) +#define VCODEC_IRQ (GIC_SPI_START + 49) +#define TV_ENC_IRQ (GIC_SPI_START + 50) +#define SMMU_VPE_CB_SC_SECURE_IRQ (GIC_SPI_START + 51) +#define SMMU_VPE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 52) +#define SMMU_VFE_CB_SC_SECURE_IRQ (GIC_SPI_START + 53) +#define SMMU_VFE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 54) +#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ (GIC_SPI_START + 55) +#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 56) +#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ (GIC_SPI_START + 57) +#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 58) +#define SMMU_ROT_CB_SC_SECURE_IRQ (GIC_SPI_START + 59) +#define SMMU_ROT_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 60) +#define SMMU_MDP1_CB_SC_SECURE_IRQ (GIC_SPI_START + 61) +#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 62) +#define SMMU_MDP0_CB_SC_SECURE_IRQ (GIC_SPI_START + 63) +#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 64) +#define SMMU_JPEGD_CB_SC_SECURE_IRQ (GIC_SPI_START + 65) +#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 66) +#define SMMU_IJPEG_CB_SC_SECURE_IRQ (GIC_SPI_START + 67) +#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 68) +#define SMMU_GFX3D_CB_SC_SECURE_IRQ (GIC_SPI_START + 69) +#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 70) +#define SMMU_GFX2D0_CB_SC_SECURE_IRQ (GIC_SPI_START + 71) +#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 72) +#define ROT_IRQ (GIC_SPI_START + 73) +#define MMSS_FABRIC_IRQ (GIC_SPI_START + 74) +#define MDP_IRQ (GIC_SPI_START + 75) +#define JPEGD_IRQ (GIC_SPI_START + 76) +#define JPEG_IRQ (GIC_SPI_START + 77) +#define MMSS_IMEM_IRQ (GIC_SPI_START + 78) +#define HDMI_IRQ (GIC_SPI_START + 79) +#define GFX3D_IRQ (GIC_SPI_START + 80) +#define GFX2D0_IRQ (GIC_SPI_START + 81) +#define DSI_IRQ (GIC_SPI_START + 82) +#define CSI_1_IRQ (GIC_SPI_START + 83) +#define CSI_0_IRQ (GIC_SPI_START + 84) +#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ (GIC_SPI_START + 85) +#define LPASS_SCSS_MIDI_IRQ (GIC_SPI_START + 86) +#define LPASS_Q6SS_WDOG_EXPIRED (GIC_SPI_START + 87) +#define LPASS_SCSS_GP_LOW_IRQ (GIC_SPI_START + 88) +#define LPASS_SCSS_GP_MEDIUM_IRQ (GIC_SPI_START + 89) +#define LPASS_SCSS_GP_HIGH_IRQ (GIC_SPI_START + 90) +#define TOP_IMEM_IRQ (GIC_SPI_START + 91) +#define FABRIC_SYS_IRQ (GIC_SPI_START + 92) +#define FABRIC_APPS_IRQ (GIC_SPI_START + 93) +#define USB1_HS_BAM_IRQ (GIC_SPI_START + 94) +#define SDC4_BAM_IRQ (GIC_SPI_START + 95) +#define SDC3_BAM_IRQ (GIC_SPI_START + 96) +#define SDC2_BAM_IRQ (GIC_SPI_START + 97) +#define SDC1_BAM_IRQ (GIC_SPI_START + 98) +#define FABRIC_SPS_IRQ (GIC_SPI_START + 99) +#define USB1_HS_IRQ (GIC_SPI_START + 100) +#define SDC4_IRQ_0 (GIC_SPI_START + 101) +#define SDC3_IRQ_0 (GIC_SPI_START + 102) +#define SDC2_IRQ_0 (GIC_SPI_START + 103) +#define SDC1_IRQ_0 (GIC_SPI_START + 104) +#define SPS_BAM_DMA_IRQ (GIC_SPI_START + 105) +#define SPS_SEC_VIOL_IRQ (GIC_SPI_START + 106) +#define SPS_MTI_0 (GIC_SPI_START + 107) +#define SPS_MTI_1 (GIC_SPI_START + 108) +#define SPS_MTI_2 (GIC_SPI_START + 109) +#define SPS_MTI_3 (GIC_SPI_START + 110) +#define SPS_MTI_4 (GIC_SPI_START + 111) +#define SPS_MTI_5 (GIC_SPI_START + 112) +#define SPS_MTI_6 (GIC_SPI_START + 113) +#define SPS_MTI_7 (GIC_SPI_START + 114) +#define SPS_MTI_8 (GIC_SPI_START + 115) +#define SPS_MTI_9 (GIC_SPI_START + 116) +#define SPS_MTI_10 (GIC_SPI_START + 117) +#define SPS_MTI_11 (GIC_SPI_START + 118) +#define SPS_MTI_12 (GIC_SPI_START + 119) +#define SPS_MTI_13 (GIC_SPI_START + 120) +#define SPS_MTI_14 (GIC_SPI_START + 121) +#define SPS_MTI_15 (GIC_SPI_START + 122) +#define SPS_MTI_16 (GIC_SPI_START + 123) +#define SPS_MTI_17 (GIC_SPI_START + 124) +#define SPS_MTI_18 (GIC_SPI_START + 125) +#define SPS_MTI_19 (GIC_SPI_START + 126) +#define SPS_MTI_20 (GIC_SPI_START + 127) +#define SPS_MTI_21 (GIC_SPI_START + 128) +#define SPS_MTI_22 (GIC_SPI_START + 129) +#define SPS_MTI_23 (GIC_SPI_START + 130) +#define SPS_MTI_24 (GIC_SPI_START + 131) +#define SPS_MTI_25 (GIC_SPI_START + 132) +#define SPS_MTI_26 (GIC_SPI_START + 133) +#define SPS_MTI_27 (GIC_SPI_START + 134) +#define SPS_MTI_28 (GIC_SPI_START + 135) +#define SPS_MTI_29 (GIC_SPI_START + 136) +#define SPS_MTI_30 (GIC_SPI_START + 137) +#define SPS_MTI_31 (GIC_SPI_START + 138) +#define UXMC_EBI2_WR_ER_DONE_IRQ (GIC_SPI_START + 139) +#define UXMC_EBI2_OP_DONE_IRQ (GIC_SPI_START + 140) +#define USB2_IRQ (GIC_SPI_START + 141) +#define USB1_IRQ (GIC_SPI_START + 142) +#define TSSC_SSBI_IRQ (GIC_SPI_START + 143) +#define TSSC_SAMPLE_IRQ (GIC_SPI_START + 144) +#define TSSC_PENUP_IRQ (GIC_SPI_START + 145) +#define INT_UART1DM_IRQ (GIC_SPI_START + 146) +#define GSBI1_QUP_IRQ (GIC_SPI_START + 147) +#define INT_UART2DM_IRQ (GIC_SPI_START + 148) +#define GSBI2_QUP_IRQ (GIC_SPI_START + 149) +#define INT_UART3DM_IRQ (GIC_SPI_START + 150) +#define GSBI3_QUP_IRQ (GIC_SPI_START + 151) +#define INT_UART4DM_IRQ (GIC_SPI_START + 152) +#define GSBI4_QUP_IRQ (GIC_SPI_START + 153) +#define INT_UART5DM_IRQ (GIC_SPI_START + 154) +#define GSBI5_QUP_IRQ (GIC_SPI_START + 155) +#define INT_UART6DM_IRQ (GIC_SPI_START + 156) +#define GSBI6_QUP_IRQ (GIC_SPI_START + 157) +#define INT_UART7DM_IRQ (GIC_SPI_START + 158) +#define GSBI7_QUP_IRQ (GIC_SPI_START + 159) +#define INT_UART8DM_IRQ (GIC_SPI_START + 160) +#define GSBI8_QUP_IRQ (GIC_SPI_START + 161) +#define TSIF_TSPP_IRQ (GIC_SPI_START + 162) +#define TSIF_BAM_IRQ (GIC_SPI_START + 163) +#define TSIF2_IRQ (GIC_SPI_START + 164) +#define TSIF1_IRQ (GIC_SPI_START + 165) +#define INT_ADM1_MASTER (GIC_SPI_START + 166) +#define INT_ADM1_AARM (GIC_SPI_START + 167) +#define INT_ADM1_SD2 (GIC_SPI_START + 168) +#define INT_ADM1_SD3 (GIC_SPI_START + 169) +#define INT_ADM0_MASTER (GIC_SPI_START + 170) +#define INT_ADM0_AARM (GIC_SPI_START + 171) +#define INT_ADM0_SD2 (GIC_SPI_START + 172) +#define INT_ADM0_SD3 (GIC_SPI_START + 173) +#define CC_SCSS_WDT1CPU1BITEEXPIRED (GIC_SPI_START + 174) +#define CC_SCSS_WDT1CPU0BITEEXPIRED (GIC_SPI_START + 175) +#define CC_SCSS_WDT0CPU1BITEEXPIRED (GIC_SPI_START + 176) +#define CC_SCSS_WDT0CPU0BITEEXPIRED (GIC_SPI_START + 177) +#define TSENS_UPPER_LOWER_INT (GIC_SPI_START + 178) +#define SSBI2_2_SC_CPU1_SECURE_INT (GIC_SPI_START + 179) +#define SSBI2_2_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 180) +#define SSBI2_1_SC_CPU1_SECURE_INT (GIC_SPI_START + 181) +#define SSBI2_1_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 182) +#define XPU_SUMMARY_IRQ (GIC_SPI_START + 183) +#define BUS_EXCEPTION_SUMMARY_IRQ (GIC_SPI_START + 184) +#define HSDDRX_SMICH0_IRQ (GIC_SPI_START + 185) +#define HSDDRX_EBI1_IRQ (GIC_SPI_START + 186) +#define SDC5_BAM_IRQ (GIC_SPI_START + 187) +#define SDC5_IRQ_0 (GIC_SPI_START + 188) +#define INT_UART9DM_IRQ (GIC_SPI_START + 189) +#define GSBI9_QUP_IRQ (GIC_SPI_START + 190) +#define INT_UART10DM_IRQ (GIC_SPI_START + 191) +#define GSBI10_QUP_IRQ (GIC_SPI_START + 192) +#define INT_UART11DM_IRQ (GIC_SPI_START + 193) +#define GSBI11_QUP_IRQ (GIC_SPI_START + 194) +#define INT_UART12DM_IRQ (GIC_SPI_START + 195) +#define GSBI12_QUP_IRQ (GIC_SPI_START + 196) +/*SPI 197 to 216 arent used in 8x60*/ +#define SMPSS_SPARE_1 (GIC_SPI_START + 217) +#define SMPSS_SPARE_2 (GIC_SPI_START + 218) +#define SMPSS_SPARE_3 (GIC_SPI_START + 219) +#define SMPSS_SPARE_4 (GIC_SPI_START + 220) +#define SMPSS_SPARE_5 (GIC_SPI_START + 221) +#define SMPSS_SPARE_6 (GIC_SPI_START + 222) +#define SMPSS_SPARE_7 (GIC_SPI_START + 223) + +#define NR_GPIO_IRQS 173 +#define NR_MSM_IRQS 256 +#define NR_BOARD_IRQS 0 + +#endif diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h index 164d355..8679a45 100644 --- a/arch/arm/mach-msm/include/mach/irqs.h +++ b/arch/arm/mach-msm/include/mach/irqs.h @@ -24,6 +24,8 @@ #elif defined(CONFIG_ARCH_QSD8X50) #include "irqs-8x50.h" #include "sirc.h" +#elif defined(CONFIG_ARCH_MSM8X60) +#include "irqs-8x60.h" #elif defined(CONFIG_ARCH_MSM_ARM11) #include "irqs-7x00.h" #else diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index 50c7847..070e17d 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -23,6 +23,8 @@ #define PHYS_OFFSET UL(0x20000000) #elif defined(CONFIG_ARCH_MSM7X30) #define PHYS_OFFSET UL(0x00200000) +#elif defined(CONFIG_ARCH_MSM8X60) +#define PHYS_OFFSET UL(0x40200000) #else #define PHYS_OFFSET UL(0x10000000) #endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h new file mode 100644 index 0000000..45bab50 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_8X60_H +#define __ASM_ARCH_MSM_IOMAP_8X60_H + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * MSM_VIC_BASE must be an value that can be loaded via a "mov" + * instruction, otherwise entry-macro.S will not compile. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + +#define MSM_QGIC_DIST_BASE IOMEM(0xF0000000) +#define MSM_QGIC_DIST_PHYS 0x02080000 +#define MSM_QGIC_DIST_SIZE SZ_4K + +#define MSM_QGIC_CPU_BASE IOMEM(0xF0001000) +#define MSM_QGIC_CPU_PHYS 0x02081000 +#define MSM_QGIC_CPU_SIZE SZ_4K + +#define MSM_ACC_BASE IOMEM(0xF0002000) +#define MSM_ACC_PHYS 0x02001000 +#define MSM_ACC_SIZE SZ_4K + +#define MSM_GCC_BASE IOMEM(0xF0003000) +#define MSM_GCC_PHYS 0x02082000 +#define MSM_GCC_SIZE SZ_4K + +#define MSM_TLMM_BASE IOMEM(0xF0004000) +#define MSM_TLMM_PHYS 0x00800000 +#define MSM_TLMM_SIZE SZ_16K + +#define MSM_SHARED_RAM_BASE IOMEM(0xF0100000) +#define MSM_SHARED_RAM_SIZE SZ_1M + +#define MSM_TMR_BASE IOMEM(0xF0200000) +#define MSM_TMR_PHYS 0x02000000 +#define MSM_TMR_SIZE (SZ_1M) + +#define MSM_GPT_BASE (MSM_TMR_BASE + 0x4) +#define MSM_DGT_BASE (MSM_TMR_BASE + 0x24) + +#define MSM_IOMMU_JPEGD_PHYS 0x07300000 +#define MSM_IOMMU_JPEGD_SIZE SZ_1M + +#define MSM_IOMMU_VPE_PHYS 0x07400000 +#define MSM_IOMMU_VPE_SIZE SZ_1M + +#define MSM_IOMMU_MDP0_PHYS 0x07500000 +#define MSM_IOMMU_MDP0_SIZE SZ_1M + +#define MSM_IOMMU_MDP1_PHYS 0x07600000 +#define MSM_IOMMU_MDP1_SIZE SZ_1M + +#define MSM_IOMMU_ROT_PHYS 0x07700000 +#define MSM_IOMMU_ROT_SIZE SZ_1M + +#define MSM_IOMMU_IJPEG_PHYS 0x07800000 +#define MSM_IOMMU_IJPEG_SIZE SZ_1M + +#define MSM_IOMMU_VFE_PHYS 0x07900000 +#define MSM_IOMMU_VFE_SIZE SZ_1M + +#define MSM_IOMMU_VCODEC_A_PHYS 0x07A00000 +#define MSM_IOMMU_VCODEC_A_SIZE SZ_1M + +#define MSM_IOMMU_VCODEC_B_PHYS 0x07B00000 +#define MSM_IOMMU_VCODEC_B_SIZE SZ_1M + +#define MSM_IOMMU_GFX3D_PHYS 0x07C00000 +#define MSM_IOMMU_GFX3D_SIZE SZ_1M + +#define MSM_IOMMU_GFX2D0_PHYS 0x07D00000 +#define MSM_IOMMU_GFX2D0_SIZE SZ_1M + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h index e6b1821..8e24dd8 100644 --- a/arch/arm/mach-msm/include/mach/msm_iomap.h +++ b/arch/arm/mach-msm/include/mach/msm_iomap.h @@ -47,8 +47,12 @@ #include "msm_iomap-7x30.h" #elif defined(CONFIG_ARCH_QSD8X50) #include "msm_iomap-8x50.h" +#elif defined(CONFIG_ARCH_MSM8X60) +#include "msm_iomap-8x60.h" #else #include "msm_iomap-7x00.h" #endif + + #endif diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h new file mode 100644 index 0000000..3ff7bf5 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/smp.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __ASM_ARCH_MSM_SMP_H +#define __ASM_ARCH_MSM_SMP_H + +#include <asm/hardware/gic.h> + +static inline void smp_cross_call(const struct cpumask *mask) +{ + gic_raise_softirq(mask, 1); +} + +#endif diff --git a/arch/arm/mach-msm/include/mach/vmalloc.h b/arch/arm/mach-msm/include/mach/vmalloc.h index 05f81fd..31a32ad 100644 --- a/arch/arm/mach-msm/include/mach/vmalloc.h +++ b/arch/arm/mach-msm/include/mach/vmalloc.h @@ -16,7 +16,7 @@ #ifndef __ASM_ARCH_MSM_VMALLOC_H #define __ASM_ARCH_MSM_VMALLOC_H -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 #endif diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c index 1c05060..d36b610 100644 --- a/arch/arm/mach-msm/io.c +++ b/arch/arm/mach-msm/io.c @@ -100,6 +100,21 @@ void __init msm_map_qsd8x50_io(void) } #endif /* CONFIG_ARCH_QSD8X50 */ +#ifdef CONFIG_ARCH_MSM8X60 +static struct map_desc msm8x60_io_desc[] __initdata = { + MSM_DEVICE(QGIC_DIST), + MSM_DEVICE(QGIC_CPU), + MSM_DEVICE(TMR), + MSM_DEVICE(ACC), + MSM_DEVICE(GCC), +}; + +void __init msm_map_msm8x60_io(void) +{ + iotable_init(msm8x60_io_desc, ARRAY_SIZE(msm8x60_io_desc)); +} +#endif /* CONFIG_ARCH_MSM8X60 */ + #ifdef CONFIG_ARCH_MSM7X30 static struct map_desc msm7x30_io_desc[] __initdata = { MSM_DEVICE(VIC), diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c new file mode 100644 index 0000000..f71747d --- /dev/null +++ b/arch/arm/mach-msm/iommu.c @@ -0,0 +1,597 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/iommu.h> + +#include <asm/cacheflush.h> +#include <asm/sizes.h> + +#include <mach/iommu_hw-8xxx.h> +#include <mach/iommu.h> + +DEFINE_SPINLOCK(msm_iommu_lock); + +struct msm_priv { + unsigned long *pgtable; + struct list_head list_attached; +}; + +static void __flush_iotlb(struct iommu_domain *domain) +{ + struct msm_priv *priv = domain->priv; + struct msm_iommu_drvdata *iommu_drvdata; + struct msm_iommu_ctx_drvdata *ctx_drvdata; + +#ifndef CONFIG_IOMMU_PGTABLES_L2 + unsigned long *fl_table = priv->pgtable; + int i; + + dmac_flush_range(fl_table, fl_table + SZ_16K); + + for (i = 0; i < NUM_FL_PTE; i++) + if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) { + void *sl_table = __va(fl_table[i] & FL_BASE_MASK); + dmac_flush_range(sl_table, sl_table + SZ_4K); + } +#endif + + list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) { + if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent) + BUG(); + + iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent); + SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0); + } +} + +static void __reset_context(void __iomem *base, int ctx) +{ + SET_BPRCOSH(base, ctx, 0); + SET_BPRCISH(base, ctx, 0); + SET_BPRCNSH(base, ctx, 0); + SET_BPSHCFG(base, ctx, 0); + SET_BPMTCFG(base, ctx, 0); + SET_ACTLR(base, ctx, 0); + SET_SCTLR(base, ctx, 0); + SET_FSRRESTORE(base, ctx, 0); + SET_TTBR0(base, ctx, 0); + SET_TTBR1(base, ctx, 0); + SET_TTBCR(base, ctx, 0); + SET_BFBCR(base, ctx, 0); + SET_PAR(base, ctx, 0); + SET_FAR(base, ctx, 0); + SET_CTX_TLBIALL(base, ctx, 0); + SET_TLBFLPTER(base, ctx, 0); + SET_TLBSLPTER(base, ctx, 0); + SET_TLBLKCR(base, ctx, 0); + SET_PRRR(base, ctx, 0); + SET_NMRR(base, ctx, 0); + SET_CONTEXTIDR(base, ctx, 0); +} + +static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable) +{ + __reset_context(base, ctx); + + /* Set up HTW mode */ + /* TLB miss configuration: perform HTW on miss */ + SET_TLBMCFG(base, ctx, 0x3); + + /* V2P configuration: HTW for access */ + SET_V2PCFG(base, ctx, 0x3); + + SET_TTBCR(base, ctx, 0); + SET_TTBR0_PA(base, ctx, (pgtable >> 14)); + + /* Invalidate the TLB for this context */ + SET_CTX_TLBIALL(base, ctx, 0); + + /* Set interrupt number to "secure" interrupt */ + SET_IRPTNDX(base, ctx, 0); + + /* Enable context fault interrupt */ + SET_CFEIE(base, ctx, 1); + + /* Stall access on a context fault and let the handler deal with it */ + SET_CFCFG(base, ctx, 1); + + /* Redirect all cacheable requests to L2 slave port. */ + SET_RCISH(base, ctx, 1); + SET_RCOSH(base, ctx, 1); + SET_RCNSH(base, ctx, 1); + + /* Turn on TEX Remap */ + SET_TRE(base, ctx, 1); + + /* Do not configure PRRR / NMRR on the IOMMU for now. We will assume + * TEX class 0 for everything until attributes are properly worked out + */ + SET_PRRR(base, ctx, 0); + SET_NMRR(base, ctx, 0); + + /* Turn on BFB prefetch */ + SET_BFBDFE(base, ctx, 1); + +#ifdef CONFIG_IOMMU_PGTABLES_L2 + /* Configure page tables as inner-cacheable and shareable to reduce + * the TLB miss penalty. + */ + SET_TTBR0_SH(base, ctx, 1); + SET_TTBR1_SH(base, ctx, 1); + + SET_TTBR0_NOS(base, ctx, 1); + SET_TTBR1_NOS(base, ctx, 1); + + SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */ + SET_TTBR0_IRGNL(base, ctx, 1); + + SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */ + SET_TTBR1_IRGNL(base, ctx, 1); + + SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */ + SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */ +#endif + + /* Enable the MMU */ + SET_M(base, ctx, 1); +} + +static int msm_iommu_domain_init(struct iommu_domain *domain) +{ + struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL); + + if (!priv) + goto fail_nomem; + + INIT_LIST_HEAD(&priv->list_attached); + priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL, + get_order(SZ_16K)); + + if (!priv->pgtable) + goto fail_nomem; + + memset(priv->pgtable, 0, SZ_16K); + domain->priv = priv; + return 0; + +fail_nomem: + kfree(priv); + return -ENOMEM; +} + +static void msm_iommu_domain_destroy(struct iommu_domain *domain) +{ + struct msm_priv *priv; + unsigned long flags; + unsigned long *fl_table; + int i; + + spin_lock_irqsave(&msm_iommu_lock, flags); + priv = domain->priv; + domain->priv = NULL; + + if (priv) { + fl_table = priv->pgtable; + + for (i = 0; i < NUM_FL_PTE; i++) + if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) + free_page((unsigned long) __va(((fl_table[i]) & + FL_BASE_MASK))); + + free_pages((unsigned long)priv->pgtable, get_order(SZ_16K)); + priv->pgtable = NULL; + } + + kfree(priv); + spin_unlock_irqrestore(&msm_iommu_lock, flags); +} + +static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) +{ + struct msm_priv *priv; + struct msm_iommu_ctx_dev *ctx_dev; + struct msm_iommu_drvdata *iommu_drvdata; + struct msm_iommu_ctx_drvdata *ctx_drvdata; + struct msm_iommu_ctx_drvdata *tmp_drvdata; + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&msm_iommu_lock, flags); + + priv = domain->priv; + + if (!priv || !dev) { + ret = -EINVAL; + goto fail; + } + + iommu_drvdata = dev_get_drvdata(dev->parent); + ctx_drvdata = dev_get_drvdata(dev); + ctx_dev = dev->platform_data; + + if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) { + ret = -EINVAL; + goto fail; + } + + list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm) + if (tmp_drvdata == ctx_drvdata) { + ret = -EBUSY; + goto fail; + } + + __program_context(iommu_drvdata->base, ctx_dev->num, + __pa(priv->pgtable)); + + list_add(&(ctx_drvdata->attached_elm), &priv->list_attached); + __flush_iotlb(domain); + +fail: + spin_unlock_irqrestore(&msm_iommu_lock, flags); + return ret; +} + +static void msm_iommu_detach_dev(struct iommu_domain *domain, + struct device *dev) +{ + struct msm_priv *priv; + struct msm_iommu_ctx_dev *ctx_dev; + struct msm_iommu_drvdata *iommu_drvdata; + struct msm_iommu_ctx_drvdata *ctx_drvdata; + unsigned long flags; + + spin_lock_irqsave(&msm_iommu_lock, flags); + priv = domain->priv; + + if (!priv || !dev) + goto fail; + + iommu_drvdata = dev_get_drvdata(dev->parent); + ctx_drvdata = dev_get_drvdata(dev); + ctx_dev = dev->platform_data; + + if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) + goto fail; + + __flush_iotlb(domain); + __reset_context(iommu_drvdata->base, ctx_dev->num); + list_del_init(&ctx_drvdata->attached_elm); + +fail: + spin_unlock_irqrestore(&msm_iommu_lock, flags); +} + +static int msm_iommu_map(struct iommu_domain *domain, unsigned long va, + phys_addr_t pa, int order, int prot) +{ + struct msm_priv *priv; + unsigned long flags; + unsigned long *fl_table; + unsigned long *fl_pte; + unsigned long fl_offset; + unsigned long *sl_table; + unsigned long *sl_pte; + unsigned long sl_offset; + size_t len = 0x1000UL << order; + int ret = 0; + + spin_lock_irqsave(&msm_iommu_lock, flags); + priv = domain->priv; + + if (!priv) { + ret = -EINVAL; + goto fail; + } + + fl_table = priv->pgtable; + + if (len != SZ_16M && len != SZ_1M && + len != SZ_64K && len != SZ_4K) { + pr_debug("Bad size: %d\n", len); + ret = -EINVAL; + goto fail; + } + + if (!fl_table) { + pr_debug("Null page table\n"); + ret = -EINVAL; + goto fail; + } + + fl_offset = FL_OFFSET(va); /* Upper 12 bits */ + fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */ + + if (len == SZ_16M) { + int i = 0; + for (i = 0; i < 16; i++) + *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION | + FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT | + FL_SHARED; + } + + if (len == SZ_1M) + *fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | + FL_TYPE_SECT | FL_SHARED; + + /* Need a 2nd level table */ + if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) { + unsigned long *sl; + sl = (unsigned long *) __get_free_pages(GFP_KERNEL, + get_order(SZ_4K)); + + if (!sl) { + pr_debug("Could not allocate second level table\n"); + ret = -ENOMEM; + goto fail; + } + + memset(sl, 0, SZ_4K); + *fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE); + } + + sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK)); + sl_offset = SL_OFFSET(va); + sl_pte = sl_table + sl_offset; + + + if (len == SZ_4K) + *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | + SL_SHARED | SL_TYPE_SMALL; + + if (len == SZ_64K) { + int i; + + for (i = 0; i < 16; i++) + *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 | + SL_AP1 | SL_SHARED | SL_TYPE_LARGE; + } + + __flush_iotlb(domain); +fail: + spin_unlock_irqrestore(&msm_iommu_lock, flags); + return ret; +} + +static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va, + int order) +{ + struct msm_priv *priv; + unsigned long flags; + unsigned long *fl_table; + unsigned long *fl_pte; + unsigned long fl_offset; + unsigned long *sl_table; + unsigned long *sl_pte; + unsigned long sl_offset; + size_t len = 0x1000UL << order; + int i, ret = 0; + + spin_lock_irqsave(&msm_iommu_lock, flags); + + priv = domain->priv; + + if (!priv) { + ret = -ENODEV; + goto fail; + } + + fl_table = priv->pgtable; + + if (len != SZ_16M && len != SZ_1M && + len != SZ_64K && len != SZ_4K) { + pr_debug("Bad length: %d\n", len); + ret = -EINVAL; + goto fail; + } + + if (!fl_table) { + pr_debug("Null page table\n"); + ret = -EINVAL; + goto fail; + } + + fl_offset = FL_OFFSET(va); /* Upper 12 bits */ + fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */ + + if (*fl_pte == 0) { + pr_debug("First level PTE is 0\n"); + ret = -ENODEV; + goto fail; + } + + /* Unmap supersection */ + if (len == SZ_16M) + for (i = 0; i < 16; i++) + *(fl_pte+i) = 0; + + if (len == SZ_1M) + *fl_pte = 0; + + sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK)); + sl_offset = SL_OFFSET(va); + sl_pte = sl_table + sl_offset; + + if (len == SZ_64K) { + for (i = 0; i < 16; i++) + *(sl_pte+i) = 0; + } + + if (len == SZ_4K) + *sl_pte = 0; + + if (len == SZ_4K || len == SZ_64K) { + int used = 0; + + for (i = 0; i < NUM_SL_PTE; i++) + if (sl_table[i]) + used = 1; + if (!used) { + free_page((unsigned long)sl_table); + *fl_pte = 0; + } + } + + __flush_iotlb(domain); +fail: + spin_unlock_irqrestore(&msm_iommu_lock, flags); + return ret; +} + +static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain, + unsigned long va) +{ + struct msm_priv *priv; + struct msm_iommu_drvdata *iommu_drvdata; + struct msm_iommu_ctx_drvdata *ctx_drvdata; + unsigned int par; + unsigned long flags; + void __iomem *base; + phys_addr_t ret = 0; + int ctx; + + spin_lock_irqsave(&msm_iommu_lock, flags); + + priv = domain->priv; + if (list_empty(&priv->list_attached)) + goto fail; + + ctx_drvdata = list_entry(priv->list_attached.next, + struct msm_iommu_ctx_drvdata, attached_elm); + iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent); + + base = iommu_drvdata->base; + ctx = ctx_drvdata->num; + + /* Invalidate context TLB */ + SET_CTX_TLBIALL(base, ctx, 0); + SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT); + + if (GET_FAULT(base, ctx)) + goto fail; + + par = GET_PAR(base, ctx); + + /* We are dealing with a supersection */ + if (GET_NOFAULT_SS(base, ctx)) + ret = (par & 0xFF000000) | (va & 0x00FFFFFF); + else /* Upper 20 bits from PAR, lower 12 from VA */ + ret = (par & 0xFFFFF000) | (va & 0x00000FFF); + +fail: + spin_unlock_irqrestore(&msm_iommu_lock, flags); + return ret; +} + +static int msm_iommu_domain_has_cap(struct iommu_domain *domain, + unsigned long cap) +{ + return 0; +} + +static void print_ctx_regs(void __iomem *base, int ctx) +{ + unsigned int fsr = GET_FSR(base, ctx); + pr_err("FAR = %08x PAR = %08x\n", + GET_FAR(base, ctx), GET_PAR(base, ctx)); + pr_err("FSR = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr, + (fsr & 0x02) ? "TF " : "", + (fsr & 0x04) ? "AFF " : "", + (fsr & 0x08) ? "APF " : "", + (fsr & 0x10) ? "TLBMF " : "", + (fsr & 0x20) ? "HTWDEEF " : "", + (fsr & 0x40) ? "HTWSEEF " : "", + (fsr & 0x80) ? "MHF " : "", + (fsr & 0x10000) ? "SL " : "", + (fsr & 0x40000000) ? "SS " : "", + (fsr & 0x80000000) ? "MULTI " : ""); + + pr_err("FSYNR0 = %08x FSYNR1 = %08x\n", + GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx)); + pr_err("TTBR0 = %08x TTBR1 = %08x\n", + GET_TTBR0(base, ctx), GET_TTBR1(base, ctx)); + pr_err("SCTLR = %08x ACTLR = %08x\n", + GET_SCTLR(base, ctx), GET_ACTLR(base, ctx)); + pr_err("PRRR = %08x NMRR = %08x\n", + GET_PRRR(base, ctx), GET_NMRR(base, ctx)); +} + +irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id) +{ + struct msm_iommu_drvdata *drvdata = dev_id; + void __iomem *base; + unsigned int fsr = 0; + int ncb = 0, i = 0; + + spin_lock(&msm_iommu_lock); + + if (!drvdata) { + pr_err("Invalid device ID in context interrupt handler\n"); + goto fail; + } + + base = drvdata->base; + + pr_err("===== WOAH! =====\n"); + pr_err("Unexpected IOMMU page fault!\n"); + pr_err("base = %08x\n", (unsigned int) base); + + ncb = GET_NCB(base)+1; + for (i = 0; i < ncb; i++) { + fsr = GET_FSR(base, i); + if (fsr) { + pr_err("Fault occurred in context %d.\n", i); + pr_err("Interesting registers:\n"); + print_ctx_regs(base, i); + SET_FSR(base, i, 0x4000000F); + } + } +fail: + spin_unlock(&msm_iommu_lock); + return 0; +} + +static struct iommu_ops msm_iommu_ops = { + .domain_init = msm_iommu_domain_init, + .domain_destroy = msm_iommu_domain_destroy, + .attach_dev = msm_iommu_attach_dev, + .detach_dev = msm_iommu_detach_dev, + .map = msm_iommu_map, + .unmap = msm_iommu_unmap, + .iova_to_phys = msm_iommu_iova_to_phys, + .domain_has_cap = msm_iommu_domain_has_cap +}; + +static int msm_iommu_init(void) +{ + register_iommu(&msm_iommu_ops); + return 0; +} + +subsys_initcall(msm_iommu_init); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c new file mode 100644 index 0000000..c33ae78 --- /dev/null +++ b/arch/arm/mach-msm/iommu_dev.c @@ -0,0 +1,374 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/iommu.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/slab.h> + +#include <mach/iommu_hw-8xxx.h> +#include <mach/iommu.h> + +struct iommu_ctx_iter_data { + /* input */ + const char *name; + + /* output */ + struct device *dev; +}; + +static struct platform_device *msm_iommu_root_dev; + +static int each_iommu_ctx(struct device *dev, void *data) +{ + struct iommu_ctx_iter_data *res = data; + struct msm_iommu_ctx_dev *c = dev->platform_data; + + if (!res || !c || !c->name || !res->name) + return -EINVAL; + + if (!strcmp(res->name, c->name)) { + res->dev = dev; + return 1; + } + return 0; +} + +static int each_iommu(struct device *dev, void *data) +{ + return device_for_each_child(dev, data, each_iommu_ctx); +} + +struct device *msm_iommu_get_ctx(const char *ctx_name) +{ + struct iommu_ctx_iter_data r; + int found; + + if (!msm_iommu_root_dev) { + pr_err("No root IOMMU device.\n"); + goto fail; + } + + r.name = ctx_name; + found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu); + + if (!found) { + pr_err("Could not find context <%s>\n", ctx_name); + goto fail; + } + + return r.dev; +fail: + return NULL; +} +EXPORT_SYMBOL(msm_iommu_get_ctx); + +static void msm_iommu_reset(void __iomem *base) +{ + int ctx, ncb; + + SET_RPUE(base, 0); + SET_RPUEIE(base, 0); + SET_ESRRESTORE(base, 0); + SET_TBE(base, 0); + SET_CR(base, 0); + SET_SPDMBE(base, 0); + SET_TESTBUSCR(base, 0); + SET_TLBRSW(base, 0); + SET_GLOBAL_TLBIALL(base, 0); + SET_RPU_ACR(base, 0); + SET_TLBLKCRWE(base, 1); + ncb = GET_NCB(base)+1; + + for (ctx = 0; ctx < ncb; ctx++) { + SET_BPRCOSH(base, ctx, 0); + SET_BPRCISH(base, ctx, 0); + SET_BPRCNSH(base, ctx, 0); + SET_BPSHCFG(base, ctx, 0); + SET_BPMTCFG(base, ctx, 0); + SET_ACTLR(base, ctx, 0); + SET_SCTLR(base, ctx, 0); + SET_FSRRESTORE(base, ctx, 0); + SET_TTBR0(base, ctx, 0); + SET_TTBR1(base, ctx, 0); + SET_TTBCR(base, ctx, 0); + SET_BFBCR(base, ctx, 0); + SET_PAR(base, ctx, 0); + SET_FAR(base, ctx, 0); + SET_CTX_TLBIALL(base, ctx, 0); + SET_TLBFLPTER(base, ctx, 0); + SET_TLBSLPTER(base, ctx, 0); + SET_TLBLKCR(base, ctx, 0); + SET_PRRR(base, ctx, 0); + SET_NMRR(base, ctx, 0); + SET_CONTEXTIDR(base, ctx, 0); + } +} + +static int msm_iommu_probe(struct platform_device *pdev) +{ + struct resource *r; + struct clk *iommu_clk; + struct msm_iommu_drvdata *drvdata; + struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data; + void __iomem *regs_base; + resource_size_t len; + int ret = 0, ncb, nm2v, irq; + + if (pdev->id != -1) { + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + + if (!drvdata) { + ret = -ENOMEM; + goto fail; + } + + if (!iommu_dev) { + ret = -ENODEV; + goto fail; + } + + if (iommu_dev->clk_rate != 0) { + iommu_clk = clk_get(&pdev->dev, "iommu_clk"); + + if (IS_ERR(iommu_clk)) { + ret = -ENODEV; + goto fail; + } + + if (iommu_dev->clk_rate > 0) { + ret = clk_set_rate(iommu_clk, + iommu_dev->clk_rate); + if (ret) { + clk_put(iommu_clk); + goto fail; + } + } + + ret = clk_enable(iommu_clk); + if (ret) { + clk_put(iommu_clk); + goto fail; + } + clk_put(iommu_clk); + } + + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "physbase"); + if (!r) { + ret = -ENODEV; + goto fail; + } + + len = r->end - r->start + 1; + + r = request_mem_region(r->start, len, r->name); + if (!r) { + pr_err("Could not request memory region: " + "start=%p, len=%d\n", (void *) r->start, len); + ret = -EBUSY; + goto fail; + } + + regs_base = ioremap(r->start, len); + + if (!regs_base) { + pr_err("Could not ioremap: start=%p, len=%d\n", + (void *) r->start, len); + ret = -EBUSY; + goto fail; + } + + irq = platform_get_irq_byname(pdev, "secure_irq"); + if (irq < 0) { + ret = -ENODEV; + goto fail; + } + + mb(); + + if (GET_IDR(regs_base) == 0) { + pr_err("Invalid IDR value detected\n"); + ret = -ENODEV; + goto fail; + } + + ret = request_irq(irq, msm_iommu_fault_handler, 0, + "msm_iommu_secure_irpt_handler", drvdata); + if (ret) { + pr_err("Request IRQ %d failed with ret=%d\n", irq, ret); + goto fail; + } + + msm_iommu_reset(regs_base); + drvdata->base = regs_base; + drvdata->irq = irq; + + nm2v = GET_NM2VCBMT((unsigned long) regs_base); + ncb = GET_NCB((unsigned long) regs_base); + + pr_info("device %s mapped at %p, irq %d with %d ctx banks\n", + iommu_dev->name, regs_base, irq, ncb+1); + + platform_set_drvdata(pdev, drvdata); + } else + msm_iommu_root_dev = pdev; + + return 0; + +fail: + kfree(drvdata); + return ret; +} + +static int msm_iommu_remove(struct platform_device *pdev) +{ + struct msm_iommu_drvdata *drv = NULL; + + drv = platform_get_drvdata(pdev); + if (drv) { + memset(drv, 0, sizeof(struct msm_iommu_drvdata)); + kfree(drv); + platform_set_drvdata(pdev, NULL); + } + return 0; +} + +static int msm_iommu_ctx_probe(struct platform_device *pdev) +{ + struct msm_iommu_ctx_dev *c = pdev->dev.platform_data; + struct msm_iommu_drvdata *drvdata; + struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL; + int i, ret = 0; + if (!c || !pdev->dev.parent) { + ret = -EINVAL; + goto fail; + } + + drvdata = dev_get_drvdata(pdev->dev.parent); + + if (!drvdata) { + ret = -ENODEV; + goto fail; + } + + ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL); + if (!ctx_drvdata) { + ret = -ENOMEM; + goto fail; + } + ctx_drvdata->num = c->num; + ctx_drvdata->pdev = pdev; + + INIT_LIST_HEAD(&ctx_drvdata->attached_elm); + platform_set_drvdata(pdev, ctx_drvdata); + + /* Program the M2V tables for this context */ + for (i = 0; i < MAX_NUM_MIDS; i++) { + int mid = c->mids[i]; + if (mid == -1) + break; + + SET_M2VCBR_N(drvdata->base, mid, 0); + SET_CBACR_N(drvdata->base, c->num, 0); + + /* Set VMID = MID */ + SET_VMID(drvdata->base, mid, mid); + + /* Set the context number for that MID to this context */ + SET_CBNDX(drvdata->base, mid, c->num); + + /* Set MID associated with this context bank */ + SET_CBVMID(drvdata->base, c->num, mid); + + /* Set security bit override to be Non-secure */ + SET_NSCFG(drvdata->base, mid, 3); + } + + pr_info("context device %s with bank index %d\n", c->name, c->num); + + return 0; +fail: + kfree(ctx_drvdata); + return ret; +} + +static int msm_iommu_ctx_remove(struct platform_device *pdev) +{ + struct msm_iommu_ctx_drvdata *drv = NULL; + drv = platform_get_drvdata(pdev); + if (drv) { + memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata)); + kfree(drv); + platform_set_drvdata(pdev, NULL); + } + return 0; +} + +static struct platform_driver msm_iommu_driver = { + .driver = { + .name = "msm_iommu", + }, + .probe = msm_iommu_probe, + .remove = msm_iommu_remove, +}; + +static struct platform_driver msm_iommu_ctx_driver = { + .driver = { + .name = "msm_iommu_ctx", + }, + .probe = msm_iommu_ctx_probe, + .remove = msm_iommu_ctx_remove, +}; + +static int msm_iommu_driver_init(void) +{ + int ret; + ret = platform_driver_register(&msm_iommu_driver); + if (ret != 0) { + pr_err("Failed to register IOMMU driver\n"); + goto error; + } + + ret = platform_driver_register(&msm_iommu_ctx_driver); + if (ret != 0) { + pr_err("Failed to register IOMMU context driver\n"); + goto error; + } + +error: + return ret; +} + +static void msm_iommu_driver_exit(void) +{ + platform_driver_unregister(&msm_iommu_ctx_driver); + platform_driver_unregister(&msm_iommu_driver); +} + +subsys_initcall(msm_iommu_driver_init); +module_exit(msm_iommu_driver_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index dec5ca6..7689848 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -28,7 +28,6 @@ #ifndef MSM_DGT_BASE #define MSM_DGT_BASE (MSM_GPT_BASE + 0x10) #endif -#define MSM_DGT_SHIFT (5) #define TIMER_MATCH_VAL 0x0000 #define TIMER_COUNT_VAL 0x0004 @@ -36,12 +35,28 @@ #define TIMER_ENABLE_CLR_ON_MATCH_EN 2 #define TIMER_ENABLE_EN 1 #define TIMER_CLEAR 0x000C - +#define DGT_CLK_CTL 0x0034 +enum { + DGT_CLK_CTL_DIV_1 = 0, + DGT_CLK_CTL_DIV_2 = 1, + DGT_CLK_CTL_DIV_3 = 2, + DGT_CLK_CTL_DIV_4 = 3, +}; #define CSR_PROTECTION 0x0020 #define CSR_PROTECTION_EN 1 #define GPT_HZ 32768 + +#if defined(CONFIG_ARCH_QSD8X50) +#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */ +#define MSM_DGT_SHIFT (0) +#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) +#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */ +#define MSM_DGT_SHIFT (0) +#else #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */ +#define MSM_DGT_SHIFT (5) +#endif struct msm_clock { struct clock_event_device clockevent; @@ -170,6 +185,10 @@ static void __init msm_timer_init(void) int i; int res; +#ifdef CONFIG_ARCH_MSM8X60 + writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); +#endif + for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) { struct msm_clock *clock = &msm_clocks[i]; struct clock_event_device *ce = &clock->clockevent; diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c index 2d37785..eaacb6e 100644 --- a/arch/arm/mach-mx5/cpu.c +++ b/arch/arm/mach-mx5/cpu.c @@ -70,6 +70,25 @@ int mx51_revision(void) } EXPORT_SYMBOL(mx51_revision); +#ifdef CONFIG_NEON + +/* + * All versions of the silicon before Rev. 3 have broken NEON implementations. + * Dependent on link order - so the assumption is that vfp_init is called + * before us. + */ +static int __init mx51_neon_fixup(void) +{ + if (mx51_revision() < MX51_CHIP_REV_3_0 && (elf_hwcap & HWCAP_NEON)) { + elf_hwcap &= ~HWCAP_NEON; + pr_info("Turning off NEON support, detected broken NEON implementation\n"); + } + return 0; +} + +late_initcall(mx51_neon_fixup); +#endif + static int __init post_cpu_init(void) { unsigned int reg; diff --git a/arch/arm/mach-netx/include/mach/vmalloc.h b/arch/arm/mach-netx/include/mach/vmalloc.h index 25d5cc6..7cca357 100644 --- a/arch/arm/mach-netx/include/mach/vmalloc.h +++ b/arch/arm/mach-netx/include/mach/vmalloc.h @@ -16,4 +16,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 diff --git a/arch/arm/mach-omap1/include/mach/vmalloc.h b/arch/arm/mach-omap1/include/mach/vmalloc.h index 1b2af14..b001f67 100644 --- a/arch/arm/mach-omap1/include/mach/vmalloc.h +++ b/arch/arm/mach-omap1/include/mach/vmalloc.h @@ -17,4 +17,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x18000000) +#define VMALLOC_END 0xd8000000 diff --git a/arch/arm/mach-omap2/include/mach/vmalloc.h b/arch/arm/mach-omap2/include/mach/vmalloc.h index 9ce9b6e..4da31e9 100644 --- a/arch/arm/mach-omap2/include/mach/vmalloc.h +++ b/arch/arm/mach-omap2/include/mach/vmalloc.h @@ -17,4 +17,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x38000000) +#define VMALLOC_END 0xf8000000 diff --git a/arch/arm/mach-pnx4008/include/mach/vmalloc.h b/arch/arm/mach-pnx4008/include/mach/vmalloc.h index 2ad3983..31b65ee 100644 --- a/arch/arm/mach-pnx4008/include/mach/vmalloc.h +++ b/arch/arm/mach-pnx4008/include/mach/vmalloc.h @@ -17,4 +17,4 @@ * The vmalloc() routines leaves a hole of 4kB between each vmalloced * area for the same reason. ;) */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 7aefb90..dd235ec 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -8,19 +8,16 @@ config ARCH_LUBBOCK bool "Intel DBPXA250 Development Platform (aka Lubbock)" select PXA25x select SA1111 - select PXA_HAVE_BOARD_IRQS config MACH_MAINSTONE bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)" select PXA27x select HAVE_PWM - select PXA_HAVE_BOARD_IRQS config MACH_ZYLONITE bool select PXA3xx select HAVE_PWM - select PXA_HAVE_BOARD_IRQS config MACH_ZYLONITE300 bool "PXA3xx Development Platform (aka Zylonite) PXA300/310" @@ -44,6 +41,10 @@ config MACH_TAVOREVB select PXA3xx select CPU_PXA930 +config MACH_TAVOREVB3 + bool "PXA95x Development Platform (aka TavorEVB III)" + select CPU_PXA950 + config MACH_SAAR bool "PXA930 Handheld Platform (aka SAAR)" select PXA3xx @@ -61,7 +62,6 @@ config ARCH_VIPER select ISA select I2C_GPIO select HAVE_PWM - select PXA_HAVE_BOARD_IRQS select PXA_HAVE_ISA_IRQS select ARCOM_PCMCIA @@ -69,7 +69,6 @@ config MACH_ARCOM_ZEUS bool "Arcom/Eurotech ZEUS SBC" select PXA27x select ISA - select PXA_HAVE_BOARD_IRQS select PXA_HAVE_ISA_IRQS select ARCOM_PCMCIA @@ -77,7 +76,6 @@ config MACH_BALLOON3 bool "Balloon 3 board" select PXA27x select IWMMXT - select PXA_HAVE_BOARD_IRQS config MACH_CSB726 bool "Enable Cogent CSB726 System On a Module" @@ -140,13 +138,11 @@ config MACH_INTELMOTE2 bool "Intel Mote 2 Platform" select PXA27x select IWMMXT - select PXA_HAVE_BOARD_IRQS config MACH_STARGATE2 bool "Intel Stargate 2 Platform" select PXA27x select IWMMXT - select PXA_HAVE_BOARD_IRQS config MACH_XCEP bool "Iskratel Electronics XCEP" @@ -206,13 +202,11 @@ config MACH_LOGICPD_PXA270 bool "LogicPD PXA270 Card Engine Development Platform" select PXA27x select HAVE_PWM - select PXA_HAVE_BOARD_IRQS config MACH_PCM027 bool "Phytec phyCORE-PXA270 CPU module (PCM-027)" select PXA27x select IWMMXT - select PXA_HAVE_BOARD_IRQS config MACH_PCM990_BASEBOARD bool "PHYTEC PCM-990 development board" @@ -247,7 +241,6 @@ config MACH_COLIBRI_PXA270_INCOME depends on MACH_COLIBRI select PXA27x select HAVE_PWM - select PXA_HAVE_BOARD_IRQS config MACH_COLIBRI300 bool "Toradex Colibri PXA300/310" @@ -274,7 +267,6 @@ config MACH_H4700 select PXA27x select IWMMXT select HAVE_PWM - select PXA_HAVE_BOARD_IRQS config MACH_H5000 bool "HP iPAQ h5000" @@ -289,7 +281,6 @@ config MACH_MAGICIAN select PXA27x select IWMMXT select HAVE_PWM - select PXA_HAVE_BOARD_IRQS config MACH_MIOA701 bool "Mitac Mio A701 Support" @@ -307,7 +298,6 @@ config PXA_EZX select PXA27x select IWMMXT select HAVE_PWM - select PXA_HAVE_BOARD_IRQS config MACH_EZX_A780 bool "Motorola EZX A780" @@ -478,7 +468,6 @@ config MACH_POODLE depends on PXA_SHARPSL select PXA25x select SHARP_LOCOMO - select PXA_HAVE_BOARD_IRQS config MACH_CORGI bool "Enable Sharp SL-C700 (Corgi) Support" @@ -523,7 +512,6 @@ config MACH_TOSA bool "Enable Sharp SL-6000x (Tosa) Support" depends on PXA_SHARPSL select PXA25x - select PXA_HAVE_BOARD_IRQS config TOSA_BT tristate "Control the state of built-in bluetooth chip on Sharp SL-6000" @@ -552,7 +540,6 @@ config MACH_ICONTROL config ARCH_PXA_ESERIES bool "PXA based Toshiba e-series PDAs" select PXA25x - select PXA_HAVE_BOARD_IRQS config MACH_E330 bool "Toshiba e330" @@ -606,7 +593,6 @@ config MACH_ZIPIT2 bool "Zipit Z2 Handheld" select PXA27x select HAVE_PWM - select PXA_HAVE_BOARD_IRQS endmenu @@ -643,6 +629,7 @@ config CPU_PXA300 config CPU_PXA310 bool select CPU_PXA300 + select PXA310_ULPI if USB_ULPI help PXA310 (codename Monahans-LV) @@ -692,10 +679,10 @@ config SHARPSL_PM_MAX1111 select HWMON select SENSORS_MAX1111 -config PXA_HAVE_BOARD_IRQS +config PXA_HAVE_ISA_IRQS bool -config PXA_HAVE_ISA_IRQS +config PXA310_ULPI bool endif diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 85c7fb3..e2f89c2 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -18,7 +18,7 @@ endif # SoC-specific code obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa2xx.o pxa25x.o obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o pxa2xx.o pxa27x.o -obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o +obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o obj-$(CONFIG_CPU_PXA300) += pxa300.o obj-$(CONFIG_CPU_PXA320) += pxa320.o obj-$(CONFIG_CPU_PXA930) += pxa930.o @@ -32,6 +32,7 @@ obj-$(CONFIG_MACH_ZYLONITE300) += zylonite.o zylonite_pxa300.o obj-$(CONFIG_MACH_ZYLONITE320) += zylonite.o zylonite_pxa320.o obj-$(CONFIG_MACH_LITTLETON) += littleton.o obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o +obj-$(CONFIG_MACH_TAVOREVB3) += tavorevb3.o obj-$(CONFIG_MACH_SAAR) += saar.o # 3rd Party Dev Platforms diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 9041340..79d0f6c 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -68,42 +68,6 @@ static unsigned long balloon3_pin_config[] __initdata = { /* Reset, configured as GPIO wakeup source */ GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, - - /* LEDs */ - GPIO9_GPIO, /* NAND activity LED */ - GPIO10_GPIO, /* Heartbeat LED */ - - /* AC97 */ - GPIO28_AC97_BITCLK, - GPIO29_AC97_SDATA_IN_0, - GPIO30_AC97_SDATA_OUT, - GPIO31_AC97_SYNC, - GPIO113_AC97_nRESET, - GPIO95_GPIO, - - /* MMC */ - GPIO32_MMC_CLK, - GPIO92_MMC_DAT_0, - GPIO109_MMC_DAT_1, - GPIO110_MMC_DAT_2, - GPIO111_MMC_DAT_3, - GPIO112_MMC_CMD, - - /* USB Host */ - GPIO88_USBH1_PWR, - GPIO89_USBH1_PEN, - - /* PC Card */ - GPIO48_nPOE, - GPIO49_nPWE, - GPIO50_nPIOR, - GPIO51_nPIOW, - GPIO85_nPCE_1, - GPIO54_nPCE_2, - GPIO79_PSKTSEL, - GPIO55_nPREG, - GPIO56_nPWAIT, - GPIO57_nIOIS16, }; /****************************************************************************** @@ -132,6 +96,34 @@ int __init parse_balloon3_features(char *arg) early_param("balloon3_features", parse_balloon3_features); /****************************************************************************** + * Compact Flash slot + ******************************************************************************/ +#if defined(CONFIG_PCMCIA_PXA2XX) || defined(CONFIG_PCMCIA_PXA2XX_MODULE) +static unsigned long balloon3_cf_pin_config[] __initdata = { + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO85_nPCE_1, + GPIO54_nPCE_2, + GPIO79_PSKTSEL, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, +}; + +static void __init balloon3_cf_init(void) +{ + if (!balloon3_has(BALLOON3_FEATURE_CF)) + return; + + pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_cf_pin_config)); +} +#else +static inline void balloon3_cf_init(void) {} +#endif + +/****************************************************************************** * NOR Flash ******************************************************************************/ #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) @@ -179,6 +171,15 @@ static inline void balloon3_nor_init(void) {} ******************************************************************************/ #if defined(CONFIG_TOUCHSCREEN_UCB1400) || \ defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE) +static unsigned long balloon3_ac97_pin_config[] __initdata = { + GPIO28_AC97_BITCLK, + GPIO29_AC97_SDATA_IN_0, + GPIO30_AC97_SDATA_OUT, + GPIO31_AC97_SYNC, + GPIO113_AC97_nRESET, + GPIO95_GPIO, +}; + static struct ucb1400_pdata vpac270_ucb1400_pdata = { .irq = IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ), }; @@ -197,6 +198,7 @@ static void __init balloon3_ts_init(void) if (!balloon3_has(BALLOON3_FEATURE_AUDIO)) return; + pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_ac97_pin_config)); pxa_set_ac97_info(NULL); platform_device_register(&balloon3_ucb1400_device); } @@ -208,6 +210,11 @@ static inline void balloon3_ts_init(void) {} * Framebuffer ******************************************************************************/ #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +static unsigned long balloon3_lcd_pin_config[] __initdata = { + GPIOxx_LCD_TFT_16BPP, + GPIO99_GPIO, +}; + static struct pxafb_mode_info balloon3_lcd_modes[] = { { .pixclock = 38000, @@ -242,6 +249,8 @@ static void __init balloon3_lcd_init(void) if (!balloon3_has(BALLOON3_FEATURE_TOPPOLY)) return; + pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_lcd_pin_config)); + ret = gpio_request(BALLOON3_GPIO_RUN_BACKLIGHT, "BKL-ON"); if (ret) { pr_err("Requesting BKL-ON GPIO failed!\n"); @@ -271,6 +280,15 @@ static inline void balloon3_lcd_init(void) {} * SD/MMC card controller ******************************************************************************/ #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) +static unsigned long balloon3_mmc_pin_config[] __initdata = { + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, +}; + static struct pxamci_platform_data balloon3_mci_platform_data = { .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .gpio_card_detect = -1, @@ -281,6 +299,7 @@ static struct pxamci_platform_data balloon3_mci_platform_data = { static void __init balloon3_mmc_init(void) { + pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_mmc_pin_config)); pxa_set_mci_info(&balloon3_mci_platform_data); } #else @@ -339,6 +358,11 @@ static inline void balloon3_irda_init(void) {} * USB Host ******************************************************************************/ #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static unsigned long balloon3_uhc_pin_config[] __initdata = { + GPIO88_USBH1_PWR, + GPIO89_USBH1_PEN, +}; + static struct pxaohci_platform_data balloon3_ohci_info = { .port_mode = PMM_PERPORT_MODE, .flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW, @@ -348,6 +372,7 @@ static void __init balloon3_uhc_init(void) { if (!balloon3_has(BALLOON3_FEATURE_OHCI)) return; + pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_uhc_pin_config)); pxa_set_ohci_info(&balloon3_ohci_info); } #else @@ -358,6 +383,11 @@ static inline void balloon3_uhc_init(void) {} * LEDs ******************************************************************************/ #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +static unsigned long balloon3_led_pin_config[] __initdata = { + GPIO9_GPIO, /* NAND activity LED */ + GPIO10_GPIO, /* Heartbeat LED */ +}; + struct gpio_led balloon3_gpio_leds[] = { { .name = "balloon3:green:idle", @@ -436,6 +466,7 @@ static struct platform_device balloon3_pcf_leds = { static void __init balloon3_leds_init(void) { + pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_led_pin_config)); platform_device_register(&balloon3_leds); platform_device_register(&balloon3_pcf_leds); } @@ -757,6 +788,7 @@ static void __init balloon3_init(void) balloon3_ts_init(); balloon3_udc_init(); balloon3_uhc_init(); + balloon3_cf_init(); } static struct map_desc balloon3_io_desc[] __initdata = { @@ -779,6 +811,7 @@ MACHINE_START(BALLOON3, "Balloon3") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = balloon3_map_io, + .nr_irqs = BALLOON3_NR_IRQS, .init_irq = balloon3_init_irq, .timer = &pxa_timer, .init_machine = balloon3_init, diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c index bff6e78..ad40e7b 100644 --- a/arch/arm/mach-pxa/cm-x2xx.c +++ b/arch/arm/mach-pxa/cm-x2xx.c @@ -33,6 +33,9 @@ extern void cmx255_init(void); extern void cmx270_init(void); +/* reserve IRQs for IT8152 */ +#define CMX2XX_NR_IRQS (IRQ_BOARD_START + 40) + /* virtual addresses for statically mapped regions */ #define CMX2XX_VIRT_BASE (0xe8000000) #define CMX2XX_IT8152_VIRT (CMX2XX_VIRT_BASE) @@ -514,6 +517,7 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = cmx2xx_map_io, + .nr_irqs = CMX2XX_NR_IRQS, .init_irq = cmx2xx_init_irq, .timer = &pxa_timer, .init_machine = cmx2xx_init, diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index c70e6c2..8e0b562 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/platform_device.h> +#include <linux/clk.h> #include <linux/gpio.h> #include <linux/dm9000.h> @@ -50,6 +51,7 @@ #include <plat/i2c.h> #include <plat/pxa3xx_nand.h> #include <mach/audio.h> +#include <mach/pxa3xx-u2d.h> #include <asm/mach/map.h> @@ -68,6 +70,8 @@ #define GPIO97_RTC_RD (97) #define GPIO98_RTC_IO (98) +#define GPIO_ULPI_PHY_RST (127) + static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = { /* LCD */ GPIO54_LCD_LDD_0, @@ -472,6 +476,78 @@ static void __init cm_x300_init_mmc(void) static inline void cm_x300_init_mmc(void) {} #endif +#if defined(CONFIG_PXA310_ULPI) +static struct clk *pout_clk; + +static int cm_x300_ulpi_phy_reset(void) +{ + int err; + + /* reset the PHY */ + err = gpio_request(GPIO_ULPI_PHY_RST, "ulpi reset"); + if (err) { + pr_err("%s: failed to request ULPI reset GPIO: %d\n", + __func__, err); + return err; + } + + gpio_direction_output(GPIO_ULPI_PHY_RST, 0); + msleep(10); + gpio_set_value(GPIO_ULPI_PHY_RST, 1); + msleep(10); + + gpio_free(GPIO_ULPI_PHY_RST); + + return 0; +} + +static inline int cm_x300_u2d_init(struct device *dev) +{ + int err = 0; + + if (cpu_is_pxa310()) { + /* CLK_POUT is connected to the ULPI PHY */ + pout_clk = clk_get(NULL, "CLK_POUT"); + if (IS_ERR(pout_clk)) { + err = PTR_ERR(pout_clk); + pr_err("%s: failed to get CLK_POUT: %d\n", + __func__, err); + return err; + } + clk_enable(pout_clk); + + err = cm_x300_ulpi_phy_reset(); + if (err) { + clk_disable(pout_clk); + clk_put(pout_clk); + } + } + + return err; +} + +static void cm_x300_u2d_exit(struct device *dev) +{ + if (cpu_is_pxa310()) { + clk_disable(pout_clk); + clk_put(pout_clk); + } +} + +static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = { + .ulpi_mode = ULPI_SER_6PIN, + .init = cm_x300_u2d_init, + .exit = cm_x300_u2d_exit, +}; + +static void cm_x300_init_u2d(void) +{ + pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data); +} +#else +static inline void cm_x300_init_u2d(void) {} +#endif + #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) static int cm_x300_ohci_init(struct device *dev) { @@ -754,6 +830,7 @@ static void __init cm_x300_init(void) cm_x300_init_da9030(); cm_x300_init_dm9000(); cm_x300_init_lcd(); + cm_x300_init_u2d(); cm_x300_init_ohci(); cm_x300_init_mmc(); cm_x300_init_nand(); diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c index 50d5939..58093d9 100644 --- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c +++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c @@ -312,8 +312,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, freqs.cpu = policy->cpu; if (freq_debug) - pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, " - "(SDRAM %d Mhz)\n", + pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", freqs.new / 1000, (pxa_freq_settings[idx].div2) ? (new_freq_mem / 2000) : (new_freq_mem / 1000)); diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c index 0a0d0fe..88fbec0 100644 --- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c +++ b/arch/arm/mach-pxa/cpufreq-pxa3xx.c @@ -159,7 +159,7 @@ static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy) static unsigned int pxa3xx_cpufreq_get(unsigned int cpu) { - return get_clk_frequency_khz(0); + return pxa3xx_get_clk_frequency_khz(0); } static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy, @@ -212,7 +212,8 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.min_freq = 104000; policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000; policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ - policy->cur = policy->min = policy->max = get_clk_frequency_khz(0); + policy->max = pxa3xx_get_clk_frequency_khz(0); + policy->cur = policy->min = policy->max; if (cpu_is_pxa300() || cpu_is_pxa310()) ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs)); diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 65447dc..08b4103 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -6,11 +6,12 @@ #include <asm/pmu.h> #include <mach/udc.h> +#include <mach/pxa3xx-u2d.h> #include <mach/pxafb.h> #include <mach/mmc.h> #include <mach/irda.h> #include <mach/ohci.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/pxa2xx_spi.h> #include <mach/camera.h> #include <mach/audio.h> @@ -134,6 +135,33 @@ struct platform_device pxa27x_device_udc = { } }; +#ifdef CONFIG_PXA3xx +static struct resource pxa3xx_u2d_resources[] = { + [0] = { + .start = 0x54100000, + .end = 0x54100fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USB2, + .end = IRQ_USB2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa3xx_device_u2d = { + .name = "pxa3xx-u2d", + .id = -1, + .resource = pxa3xx_u2d_resources, + .num_resources = ARRAY_SIZE(pxa3xx_u2d_resources), +}; + +void __init pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info) +{ + pxa_register_device(&pxa3xx_device_u2d, info); +} +#endif /* CONFIG_PXA3xx */ + static struct resource pxafb_resources[] = { [0] = { .start = 0x44000000, diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 50353ea..715e8bd 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -4,6 +4,7 @@ extern struct platform_device pxa3xx_device_mci2; extern struct platform_device pxa3xx_device_mci3; extern struct platform_device pxa25x_device_udc; extern struct platform_device pxa27x_device_udc; +extern struct platform_device pxa3xx_device_u2d; extern struct platform_device pxa_device_fb; extern struct platform_device pxa_device_ffuart; extern struct platform_device pxa_device_btuart; diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 0517c17..51286a7 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -43,7 +43,7 @@ #include <mach/pxafb.h> #include <mach/ohci.h> #include <mach/mmc.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <plat/i2c.h> #include <mach/camera.h> #include <mach/pxa2xx_spi.h> diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index 349212a..4971ce1 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -29,6 +29,7 @@ #include <mach/pxa25x.h> #include <mach/eseries-gpio.h> +#include <mach/eseries-irq.h> #include <mach/audio.h> #include <mach/pxafb.h> #include <mach/udc.h> @@ -183,6 +184,7 @@ MACHINE_START(E330, "Toshiba e330") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = ESERIES_NR_IRQS, .init_irq = pxa25x_init_irq, .fixup = eseries_fixup, .init_machine = e330_init, @@ -233,6 +235,7 @@ MACHINE_START(E350, "Toshiba e350") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = ESERIES_NR_IRQS, .init_irq = pxa25x_init_irq, .fixup = eseries_fixup, .init_machine = e350_init, @@ -356,6 +359,7 @@ MACHINE_START(E400, "Toshiba e400") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = ESERIES_NR_IRQS, .init_irq = pxa25x_init_irq, .fixup = eseries_fixup, .init_machine = e400_init, @@ -545,6 +549,7 @@ MACHINE_START(E740, "Toshiba e740") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = ESERIES_NR_IRQS, .init_irq = pxa25x_init_irq, .fixup = eseries_fixup, .init_machine = e740_init, @@ -737,6 +742,7 @@ MACHINE_START(E750, "Toshiba e750") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = ESERIES_NR_IRQS, .init_irq = pxa25x_init_irq, .fixup = eseries_fixup, .init_machine = e750_init, @@ -933,6 +939,7 @@ MACHINE_START(E800, "Toshiba e800") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = ESERIES_NR_IRQS, .init_irq = pxa25x_init_irq, .fixup = eseries_fixup, .init_machine = e800_init, diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c index 626c82b..f997e84 100644 --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c @@ -32,12 +32,14 @@ #include <mach/ohci.h> #include <plat/i2c.h> #include <mach/hardware.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/camera.h> #include "devices.h" #include "generic.h" +#define EZX_NR_IRQS (IRQ_BOARD_START + 24) + #define GPIO12_A780_FLIP_LID 12 #define GPIO15_A1200_FLIP_LID 15 #define GPIO15_A910_FLIP_LID 15 @@ -800,6 +802,7 @@ MACHINE_START(EZX_A780, "Motorola EZX A780") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = a780_init, @@ -866,6 +869,7 @@ MACHINE_START(EZX_E680, "Motorola EZX E680") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = e680_init, @@ -932,6 +936,7 @@ MACHINE_START(EZX_A1200, "Motorola EZX A1200") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = a1200_init, @@ -1124,6 +1129,7 @@ MACHINE_START(EZX_A910, "Motorola EZX A910") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = a910_init, @@ -1190,6 +1196,7 @@ MACHINE_START(EZX_E6, "Motorola EZX E6") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = e6_init, @@ -1230,6 +1237,7 @@ MACHINE_START(EZX_E2, "Motorola EZX E2") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = EZX_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = e2_init, diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index baabb3c..6451e9c 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -66,8 +66,7 @@ unsigned int get_clk_frequency_khz(int info) return pxa25x_get_clk_frequency_khz(info); else if (cpu_is_pxa27x()) return pxa27x_get_clk_frequency_khz(info); - else - return pxa3xx_get_clk_frequency_khz(info); + return 0; } EXPORT_SYMBOL(get_clk_frequency_khz); @@ -80,8 +79,7 @@ unsigned int get_memclk_frequency_10khz(void) return pxa25x_get_memclk_frequency_10khz(); else if (cpu_is_pxa27x()) return pxa27x_get_memclk_frequency_10khz(); - else - return pxa3xx_get_memclk_frequency_10khz(); + return 0; } EXPORT_SYMBOL(get_memclk_frequency_10khz); diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index c6305c5..4b1ad27 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -54,11 +54,9 @@ static inline void pxa2xx_clear_reset_status(unsigned int mask) {} #ifdef CONFIG_PXA3xx extern unsigned pxa3xx_get_clk_frequency_khz(int); -extern unsigned pxa3xx_get_memclk_frequency_10khz(void); extern void pxa3xx_clear_reset_status(unsigned int); #else #define pxa3xx_get_clk_frequency_khz(x) (0) -#define pxa3xx_get_memclk_frequency_10khz() (0) static inline void pxa3xx_clear_reset_status(unsigned int mask) {} #endif diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 848c861..10104f1 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -874,6 +874,7 @@ MACHINE_START(H4700, "HP iPAQ HX4700") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = HX4700_NR_IRQS, .init_irq = pxa27x_init_irq, .init_machine = hx4700_init, .timer = &pxa_timer, diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h index eec92e6..561562b 100644 --- a/arch/arm/mach-pxa/include/mach/balloon3.h +++ b/arch/arm/mach-pxa/include/mach/balloon3.h @@ -174,6 +174,8 @@ enum balloon3_features { #define BALLOON3_CODEC_IRQ IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ) #define BALLOON3_S0_CD_IRQ IRQ_GPIO(BALLOON3_GPIO_S0_CD) +#define BALLOON3_NR_IRQS (IRQ_BOARD_START + 4) + extern int balloon3_has(enum balloon3_features feature); #endif diff --git a/arch/arm/mach-pxa/include/mach/eseries-irq.h b/arch/arm/mach-pxa/include/mach/eseries-irq.h index f2a93d5..de292b2 100644 --- a/arch/arm/mach-pxa/include/mach/eseries-irq.h +++ b/arch/arm/mach-pxa/include/mach/eseries-irq.h @@ -25,3 +25,4 @@ #define TMIO_SD_IRQ IRQ_TMIO(1) #define TMIO_USB_IRQ IRQ_TMIO(2) +#define ESERIES_NR_IRQS (IRQ_BOARD_START + 16) diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h index 7f64d24..814f145 100644 --- a/arch/arm/mach-pxa/include/mach/hardware.h +++ b/arch/arm/mach-pxa/include/mach/hardware.h @@ -264,23 +264,35 @@ * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x * == 0x3 for pxa300/pxa310/pxa320 */ +#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x) #define __cpu_is_pxa2xx(id) \ ({ \ unsigned int _id = (id) >> 13 & 0x7; \ _id <= 0x2; \ }) +#else +#define __cpu_is_pxa2xx(id) (0) +#endif +#ifdef CONFIG_PXA3xx #define __cpu_is_pxa3xx(id) \ ({ \ unsigned int _id = (id) >> 13 & 0x7; \ _id == 0x3; \ }) +#else +#define __cpu_is_pxa3xx(id) (0) +#endif +#if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935) #define __cpu_is_pxa93x(id) \ ({ \ unsigned int _id = (id) >> 4 & 0xfff; \ _id == 0x683 || _id == 0x693; \ }) +#else +#define __cpu_is_pxa93x(id) (0) +#endif #define cpu_is_pxa2xx() \ ({ \ @@ -309,7 +321,7 @@ extern unsigned long get_clock_tick_rate(void); #define PCIBIOS_MIN_IO 0 #define PCIBIOS_MIN_MEM 0 #define pcibios_assign_all_busses() 1 +#define ARCH_HAS_DMA_SET_COHERENT_MASK #endif - #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-pxa/include/mach/hx4700.h b/arch/arm/mach-pxa/include/mach/hx4700.h index 9eaeed1..3740844 100644 --- a/arch/arm/mach-pxa/include/mach/hx4700.h +++ b/arch/arm/mach-pxa/include/mach/hx4700.h @@ -17,6 +17,7 @@ #define HX4700_ASIC3_GPIO_BASE NR_BUILTIN_GPIO #define HX4700_EGPIO_BASE (HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS) +#define HX4700_NR_IRQS (IRQ_BOARD_START + 70) /* * PXA GPIOs diff --git a/arch/arm/mach-pxa/include/mach/io.h b/arch/arm/mach-pxa/include/mach/io.h index 262691f..fdca3be 100644 --- a/arch/arm/mach-pxa/include/mach/io.h +++ b/arch/arm/mach-pxa/include/mach/io.h @@ -6,6 +6,8 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H +#include <mach/hardware.h> + #define IO_SPACE_LIMIT 0xffffffff /* diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h index ffc8314..d372caa 100644 --- a/arch/arm/mach-pxa/include/mach/irqs.h +++ b/arch/arm/mach-pxa/include/mach/irqs.h @@ -117,48 +117,12 @@ /* * The following interrupts are for board specific purposes. Since * the kernel can only run on one machine at a time, we can re-use - * these. There will be 16 IRQs by default. If it is not enough, - * IRQ_BOARD_END is allowed be customized for each board, but keep - * the numbers within sensible limits and in descending order, so - * when multiple config options are selected, the maximum will be - * used. + * these. + * By default, no board IRQ is reserved. It should be finished in + * custom board since sparse IRQ is already enabled. */ #define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM) -#if defined(CONFIG_MACH_H4700) -#define IRQ_BOARD_END (IRQ_BOARD_START + 70) -#elif defined(CONFIG_MACH_ZYLONITE) -#define IRQ_BOARD_END (IRQ_BOARD_START + 32) -#elif defined(CONFIG_PXA_EZX) -#define IRQ_BOARD_END (IRQ_BOARD_START + 23) -#else -#define IRQ_BOARD_END (IRQ_BOARD_START + 16) -#endif - -/* - * Figure out the MAX IRQ number. - * - * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1. - * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1 - * Otherwise, we have the standard IRQs only. - */ -#ifdef CONFIG_SA1111 -#define NR_IRQS (IRQ_BOARD_END + 55) -#elif defined(CONFIG_PXA_HAVE_BOARD_IRQS) -#define NR_IRQS (IRQ_BOARD_END) -#else #define NR_IRQS (IRQ_BOARD_START) -#endif - -/* add IT8152 IRQs beyond BOARD_END */ -#ifdef CONFIG_PCI_HOST_ITE8152 -#define IT8152_LAST_IRQ (IRQ_BOARD_END + 40) - -#if NR_IRQS < (IT8152_LAST_IRQ+1) -#undef NR_IRQS -#define NR_IRQS (IT8152_LAST_IRQ+1) -#endif - -#endif /* CONFIG_PCI_HOST_ITE8152 */ #endif /* __ASM_MACH_IRQS_H */ diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h index 6c9b21c..2a5726c 100644 --- a/arch/arm/mach-pxa/include/mach/littleton.h +++ b/arch/arm/mach-pxa/include/mach/littleton.h @@ -10,4 +10,6 @@ #define EXT0_GPIO_BASE (NR_BUILTIN_GPIO) #define EXT0_GPIO(x) (EXT0_GPIO_BASE + (x)) +#define LITTLETON_NR_IRQS (IRQ_BOARD_START + 8) + #endif /* __ASM_ARCH_LITTLETON_H */ diff --git a/arch/arm/mach-pxa/include/mach/lpd270.h b/arch/arm/mach-pxa/include/mach/lpd270.h index 0e6440c..cd07009 100644 --- a/arch/arm/mach-pxa/include/mach/lpd270.h +++ b/arch/arm/mach-pxa/include/mach/lpd270.h @@ -38,5 +38,6 @@ #define LPD270_USBC_IRQ LPD270_IRQ(2) #define LPD270_ETHERNET_IRQ LPD270_IRQ(3) #define LPD270_AC97_IRQ LPD270_IRQ(4) +#define LPD270_NR_IRQS (IRQ_BOARD_START + 5) #endif diff --git a/arch/arm/mach-pxa/include/mach/lubbock.h b/arch/arm/mach-pxa/include/mach/lubbock.h index a0d4247..2a086e8 100644 --- a/arch/arm/mach-pxa/include/mach/lubbock.h +++ b/arch/arm/mach-pxa/include/mach/lubbock.h @@ -45,6 +45,9 @@ #define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */ #define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6) +#define LUBBOCK_SA1111_IRQ_BASE (IRQ_BOARD_START + 16) +#define LUBBOCK_NR_IRQS (IRQ_BOARD_START + 16 + 55) + #ifndef __ASSEMBLY__ extern void lubbock_set_misc_wr(unsigned int mask, unsigned int set); #endif diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h index 20ef37d..0a2efcf 100644 --- a/arch/arm/mach-pxa/include/mach/magician.h +++ b/arch/arm/mach-pxa/include/mach/magician.h @@ -71,6 +71,8 @@ #define IRQ_MAGICIAN_BT (IRQ_BOARD_START + 2) #define IRQ_MAGICIAN_VBUS (IRQ_BOARD_START + 3) +#define MAGICIAN_NR_IRQS (IRQ_BOARD_START + 8) + /* * CPLD EGPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/mainstone.h b/arch/arm/mach-pxa/include/mach/mainstone.h index 86e623a..4c2d11c 100644 --- a/arch/arm/mach-pxa/include/mach/mainstone.h +++ b/arch/arm/mach-pxa/include/mach/mainstone.h @@ -134,4 +134,6 @@ #define MAINSTONE_S1_STSCHG_IRQ MAINSTONE_IRQ(14) #define MAINSTONE_S1_IRQ MAINSTONE_IRQ(15) +#define MAINSTONE_NR_IRQS (IRQ_BOARD_START + 16) + #endif diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h index 0d119d3..04f7c97 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h @@ -69,6 +69,7 @@ #define nBE0_GPIO_60 MFP_CFG(nBE0, AF0) #define nBE1_GPIO_61 MFP_CFG(nBE1, AF0) #define RDY_GPIO_62 MFP_CFG(RDY, AF0) +#define PMIC_INT_GPIO83 MFP_CFG_LPM(PMIC_INT, AF0, PULL_HIGH) /* Chip Select */ #define DF_nCS0_nCS2 MFP_CFG_LPM(DF_nCS0, AF3, PULL_HIGH) @@ -92,6 +93,9 @@ #define GPIO63_CI2C_SCL MFP_CFG_LPM(GPIO63, AF4, PULL_HIGH) #define GPIO64_CI2C_SDA MFP_CFG_LPM(GPIO64, AF4, PULL_HIGH) +#define GPIO73_CI2C_SCL MFP_CFG_LPM(GPIO73, AF1, PULL_HIGH) +#define GPIO74_CI2C_SDA MFP_CFG_LPM(GPIO74, AF1, PULL_HIGH) + #define GPIO77_CI2C_SCL MFP_CFG_LPM(GPIO77, AF2, PULL_HIGH) #define GPIO78_CI2C_SDA MFP_CFG_LPM(GPIO78, AF2, PULL_HIGH) @@ -345,6 +349,9 @@ #define GPIO69_UART1_CTS MFP_CFG(GPIO69, AF2) #define GPIO70_UART1_RTS MFP_CFG(GPIO70, AF2) +#define GPIO53_UART1_TXD MFP_CFG(GPIO53, AF2) +#define GPIO54_UART1_RXD MFP_CFG(GPIO54, AF2) + /* UART2 - BTUART */ #define GPIO91_UART2_RXD MFP_CFG(GPIO91, AF1) #define GPIO92_UART2_TXD MFP_CFG(GPIO92, AF1) diff --git a/arch/arm/mach-pxa/include/mach/pcm027.h b/arch/arm/mach-pxa/include/mach/pcm027.h index 0408326..4bac588 100644 --- a/arch/arm/mach-pxa/include/mach/pcm027.h +++ b/arch/arm/mach-pxa/include/mach/pcm027.h @@ -30,6 +30,8 @@ #define PCM027_MMCDET_IRQ PCM027_IRQ(2) #define PCM027_PM_5V_IRQ PCM027_IRQ(3) +#define PCM027_NR_IRQS (IRQ_BOARD_START + 32) + /* I2C RTC */ #define PCM027_RTC_IRQ_GPIO 0 #define PCM027_RTC_IRQ IRQ_GPIO(PCM027_RTC_IRQ_GPIO) diff --git a/arch/arm/mach-pxa/include/mach/poodle.h b/arch/arm/mach-pxa/include/mach/poodle.h index 0b3e6d0..83d1cfd 100644 --- a/arch/arm/mach-pxa/include/mach/poodle.h +++ b/arch/arm/mach-pxa/include/mach/poodle.h @@ -85,6 +85,8 @@ #define POODLE_LOCOMO_GPIO_232VCC_ON LOCOMO_GPIO(12) #define POODLE_LOCOMO_GPIO_JK_B LOCOMO_GPIO(13) +#define POODLE_NR_IRQS (IRQ_BOARD_START + 4) /* 4 for LoCoMo */ + extern struct platform_device poodle_locomo_device; #endif /* __ASM_ARCH_POODLE_H */ diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h new file mode 100644 index 0000000..9d82cb6 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h @@ -0,0 +1,35 @@ +/* + * PXA3xx U2D header + * + * Copyright (C) 2010 CompuLab Ltd. + * + * Igor Grinberg <grinberg@compulab.co.il> + * + * 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. + */ +#ifndef __PXA310_U2D__ +#define __PXA310_U2D__ + +#include <linux/usb/ulpi.h> + +struct pxa3xx_u2d_platform_data { + +#define ULPI_SER_6PIN (1 << 0) +#define ULPI_SER_3PIN (1 << 1) + unsigned int ulpi_mode; + + int (*init)(struct device *); + void (*exit)(struct device *); +}; + + +/* Start PXA3xx U2D host */ +int pxa3xx_u2d_start_hc(struct usb_bus *host); +/* Stop PXA3xx U2D host */ +void pxa3xx_u2d_stop_hc(struct usb_bus *host); + +extern void pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info); + +#endif /* __PXA310_U2D__ */ diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h index 1bbd1f2..1272c4b 100644 --- a/arch/arm/mach-pxa/include/mach/tosa.h +++ b/arch/arm/mach-pxa/include/mach/tosa.h @@ -20,6 +20,7 @@ /* Jacket Scoop */ #define TOSA_SCOOP_PHYS (PXA_CS5_PHYS + 0x00800000) +#define TOSA_NR_IRQS (IRQ_BOARD_START + TC6393XB_NR_IRQS) /* * SCOOP2 internal GPIOs */ diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h index 6e11997..faa408a 100644 --- a/arch/arm/mach-pxa/include/mach/zeus.h +++ b/arch/arm/mach-pxa/include/mach/zeus.h @@ -15,6 +15,8 @@ #ifndef _MACH_ZEUS_H #define _MACH_ZEUS_H +#define ZEUS_NR_IRQS (IRQ_BOARD_START + 48) + /* Physical addresses */ #define ZEUS_FLASH_PHYS PXA_CS0_PHYS #define ZEUS_ETH0_PHYS PXA_CS1_PHYS diff --git a/arch/arm/mach-pxa/include/mach/zylonite.h b/arch/arm/mach-pxa/include/mach/zylonite.h index 9edf645..ea24998 100644 --- a/arch/arm/mach-pxa/include/mach/zylonite.h +++ b/arch/arm/mach-pxa/include/mach/zylonite.h @@ -5,6 +5,8 @@ #define EXT_GPIO(x) (128 + (x)) +#define ZYLONITE_NR_IRQS (IRQ_BOARD_START + 32) + /* the following variables are processor specific and initialized * by the corresponding zylonite_pxa3xx_init() */ diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index 9b90461..eb58506 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -43,7 +43,7 @@ #include <mach/pxafb.h> #include <mach/mmc.h> #include <mach/pxa2xx_spi.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/littleton.h> #include <plat/i2c.h> #include <plat/pxa3xx_nand.h> @@ -441,6 +441,7 @@ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleto .boot_params = 0xa0000100, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = pxa_map_io, + .nr_irqs = LITTLETON_NR_IRQS, .init_irq = pxa3xx_init_irq, .timer = &pxa_timer, .init_machine = littleton_init, diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index d279507..fc9502e 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -509,6 +509,7 @@ MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = lpd270_map_io, + .nr_irqs = LPD270_NR_IRQS, .init_irq = lpd270_init_irq, .timer = &pxa_timer, .init_machine = lpd270_init, diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 330c328..1956c23 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -229,7 +229,7 @@ static struct resource sa1111_resources[] = { }; static struct sa1111_platform_data sa1111_info = { - .irq_base = IRQ_BOARD_END, + .irq_base = LUBBOCK_SA1111_IRQ_BASE, }; static struct platform_device sa1111_device = { @@ -560,6 +560,7 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = lubbock_map_io, + .nr_irqs = LUBBOCK_NR_IRQS, .init_irq = lubbock_init_irq, .timer = &pxa_timer, .init_machine = lubbock_init, diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index e81dd0c..42a0c2b 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -768,6 +768,7 @@ MACHINE_START(MAGICIAN, "HTC Magician") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .nr_irqs = MAGICIAN_NR_IRQS, .init_irq = pxa27x_init_irq, .init_machine = magician_init, .timer = &pxa_timer, diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 5543c64..8b71002 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -50,7 +50,7 @@ #include <mach/mmc.h> #include <mach/irda.h> #include <mach/ohci.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include "generic.h" #include "devices.h" @@ -628,6 +628,7 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") .boot_params = 0xa0000100, /* BLOB boot parameter setting */ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = mainstone_map_io, + .nr_irqs = MAINSTONE_NR_IRQS, .init_irq = mainstone_init_irq, .timer = &pxa_timer, .init_machine = mainstone_init, diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index dc66942..ffb3f5a 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -45,7 +45,7 @@ #include <mach/pxa27x.h> #include <mach/regs-rtc.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/pxafb.h> #include <mach/mmc.h> #include <mach/udc.h> diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c index 77ad6d3..405b92a 100644 --- a/arch/arm/mach-pxa/palm27x.c +++ b/arch/arm/mach-pxa/palm27x.c @@ -469,9 +469,13 @@ static struct i2c_board_info __initdata palm27x_pi2c_board_info[] = { }, }; +static struct i2c_pxa_platform_data palm27x_i2c_power_info = { + .use_pio = 1, +}; + void __init palm27x_pmic_init(void) { i2c_register_board_info(1, ARRAY_AND_SIZE(palm27x_pi2c_board_info)); - pxa27x_set_i2c_power_info(NULL); + pxa27x_set_i2c_power_info(&palm27x_i2c_power_info); } #endif diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c index 91038ee..3ff0c4a 100644 --- a/arch/arm/mach-pxa/palmld.c +++ b/arch/arm/mach-pxa/palmld.c @@ -39,7 +39,7 @@ #include <mach/mmc.h> #include <mach/pxafb.h> #include <mach/irda.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/palmasoc.h> #include <mach/palm27x.h> diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c index 1c28199..5b9f766 100644 --- a/arch/arm/mach-pxa/palmt5.c +++ b/arch/arm/mach-pxa/palmt5.c @@ -39,7 +39,7 @@ #include <mach/mmc.h> #include <mach/pxafb.h> #include <mach/irda.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/udc.h> #include <mach/palmasoc.h> #include <mach/palm27x.h> diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index 52defd5..f685a60 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c @@ -39,7 +39,7 @@ #include <mach/mmc.h> #include <mach/pxafb.h> #include <mach/irda.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/udc.h> #include <mach/ohci.h> #include <mach/pxa2xx-regs.h> diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 144dc2b..89a3792 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -43,7 +43,7 @@ #include <mach/mmc.h> #include <mach/pxafb.h> #include <mach/irda.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/udc.h> #include <mach/palmasoc.h> #include <mach/palm27x.h> diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 87e4b10..38f4425 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -41,7 +41,7 @@ #include <mach/mmc.h> #include <mach/pxafb.h> #include <mach/irda.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/udc.h> #include <mach/palmasoc.h> #include <mach/palm27x.h> diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c index 2190af0..90b08ba 100644 --- a/arch/arm/mach-pxa/pcm027.c +++ b/arch/arm/mach-pxa/pcm027.c @@ -262,6 +262,7 @@ MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = pcm027_map_io, + .nr_irqs = PCM027_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = pcm027_init, diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 55e8fcd..c04e025 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -469,6 +469,7 @@ MACHINE_START(POODLE, "SHARP Poodle") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_poodle, .map_io = pxa_map_io, + .nr_irqs = POODLE_NR_IRQS, /* 4 for LoCoMo */ .init_irq = pxa25x_init_irq, .timer = &pxa_timer, .init_machine = poodle_init, diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c new file mode 100644 index 0000000..ce7168b --- /dev/null +++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c @@ -0,0 +1,400 @@ +/* + * linux/arch/arm/mach-pxa/pxa3xx-ulpi.c + * + * code specific to pxa3xx aka Monahans + * + * Copyright (C) 2010 CompuLab Ltd. + * + * 2010-13-07: Igor Grinberg <grinberg@compulab.co.il> + * initial version: pxa310 USB Host mode support + * + * 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/kernel.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/usb.h> +#include <linux/usb/otg.h> + +#include <mach/hardware.h> +#include <mach/regs-u2d.h> +#include <mach/pxa3xx-u2d.h> + +struct pxa3xx_u2d_ulpi { + struct clk *clk; + void __iomem *mmio_base; + + struct otg_transceiver *otg; + unsigned int ulpi_mode; +}; + +static struct pxa3xx_u2d_ulpi *u2d; + +static inline u32 u2d_readl(u32 reg) +{ + return __raw_readl(u2d->mmio_base + reg); +} + +static inline void u2d_writel(u32 reg, u32 val) +{ + __raw_writel(val, u2d->mmio_base + reg); +} + +#if defined(CONFIG_PXA310_ULPI) +enum u2d_ulpi_phy_mode { + SYNCH = 0, + CARKIT = (1 << 0), + SER_3PIN = (1 << 1), + SER_6PIN = (1 << 2), + LOWPOWER = (1 << 3), +}; + +static inline enum u2d_ulpi_phy_mode pxa310_ulpi_get_phymode(void) +{ + return (u2d_readl(U2DOTGUSR) >> 28) & 0xF; +} + +static int pxa310_ulpi_poll(void) +{ + int timeout = 50000; + + while (timeout--) { + if (!(u2d_readl(U2DOTGUCR) & U2DOTGUCR_RUN)) + return 0; + + cpu_relax(); + } + + pr_warning("%s: ULPI access timed out!\n", __func__); + + return -ETIMEDOUT; +} + +static int pxa310_ulpi_read(struct otg_transceiver *otg, u32 reg) +{ + int err; + + if (pxa310_ulpi_get_phymode() != SYNCH) { + pr_warning("%s: PHY is not in SYNCH mode!\n", __func__); + return -EBUSY; + } + + u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | U2DOTGUCR_RNW | (reg << 16)); + msleep(5); + + err = pxa310_ulpi_poll(); + if (err) + return err; + + return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA; +} + +static int pxa310_ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) +{ + if (pxa310_ulpi_get_phymode() != SYNCH) { + pr_warning("%s: PHY is not in SYNCH mode!\n", __func__); + return -EBUSY; + } + + u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | (reg << 16) | (val << 8)); + msleep(5); + + return pxa310_ulpi_poll(); +} + +struct otg_io_access_ops pxa310_ulpi_access_ops = { + .read = pxa310_ulpi_read, + .write = pxa310_ulpi_write, +}; + +static void pxa310_otg_transceiver_rtsm(void) +{ + u32 u2dotgcr; + + /* put PHY to sync mode */ + u2dotgcr = u2d_readl(U2DOTGCR); + u2dotgcr |= U2DOTGCR_RTSM | U2DOTGCR_UTMID; + u2d_writel(U2DOTGCR, u2dotgcr); + msleep(10); + + /* setup OTG sync mode */ + u2dotgcr = u2d_readl(U2DOTGCR); + u2dotgcr |= U2DOTGCR_ULAF; + u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF); + u2d_writel(U2DOTGCR, u2dotgcr); +} + +static int pxa310_start_otg_host_transcvr(struct usb_bus *host) +{ + int err; + + pxa310_otg_transceiver_rtsm(); + + err = otg_init(u2d->otg); + if (err) { + pr_err("OTG transceiver init failed"); + return err; + } + + err = otg_set_vbus(u2d->otg, 1); + if (err) { + pr_err("OTG transceiver VBUS set failed"); + return err; + } + + err = otg_set_host(u2d->otg, host); + if (err) + pr_err("OTG transceiver Host mode set failed"); + + return err; +} + +static int pxa310_start_otg_hc(struct usb_bus *host) +{ + u32 u2dotgcr; + int err; + + /* disable USB device controller */ + u2d_writel(U2DCR, u2d_readl(U2DCR) & ~U2DCR_UDE); + u2d_writel(U2DOTGCR, u2d_readl(U2DOTGCR) | U2DOTGCR_UTMID); + u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F); + + err = pxa310_start_otg_host_transcvr(host); + if (err) + return err; + + /* set xceiver mode */ + if (u2d->ulpi_mode & ULPI_IC_6PIN_SERIAL) + u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) & ~U2DP3CR_P2SS); + else if (u2d->ulpi_mode & ULPI_IC_3PIN_SERIAL) + u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) | U2DP3CR_P2SS); + + /* start OTG host controller */ + u2dotgcr = u2d_readl(U2DOTGCR) | U2DOTGCR_SMAF; + u2d_writel(U2DOTGCR, u2dotgcr & ~(U2DOTGCR_ULAF | U2DOTGCR_CKAF)); + + return 0; +} + +static void pxa310_stop_otg_hc(void) +{ + pxa310_otg_transceiver_rtsm(); + + otg_set_host(u2d->otg, NULL); + otg_set_vbus(u2d->otg, 0); + otg_shutdown(u2d->otg); +} + +static void pxa310_u2d_setup_otg_hc(void) +{ + u32 u2dotgcr; + + u2dotgcr = u2d_readl(U2DOTGCR); + u2dotgcr |= U2DOTGCR_ULAF | U2DOTGCR_UTMID; + u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF); + u2d_writel(U2DOTGCR, u2dotgcr); + msleep(5); + u2d_writel(U2DOTGCR, u2dotgcr | U2DOTGCR_ULE); + msleep(5); + u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F); +} + +static int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata) +{ + unsigned int ulpi_mode = ULPI_OTG_DRVVBUS; + + if (pdata) { + if (pdata->ulpi_mode & ULPI_SER_6PIN) + ulpi_mode |= ULPI_IC_6PIN_SERIAL; + else if (pdata->ulpi_mode & ULPI_SER_3PIN) + ulpi_mode |= ULPI_IC_3PIN_SERIAL; + } + + u2d->ulpi_mode = ulpi_mode; + + u2d->otg = otg_ulpi_create(&pxa310_ulpi_access_ops, ulpi_mode); + if (!u2d->otg) + return -ENOMEM; + + u2d->otg->io_priv = u2d->mmio_base; + + return 0; +} + +static void pxa310_otg_exit(void) +{ + kfree(u2d->otg); +} +#else +static inline void pxa310_u2d_setup_otg_hc(void) {} +static inline int pxa310_start_otg_hc(struct usb_bus *host) +{ + return 0; +} +static inline void pxa310_stop_otg_hc(void) {} +static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata) +{ + return 0; +} +static inline void pxa310_otg_exit(void) {} +#endif /* CONFIG_PXA310_ULPI */ + +int pxa3xx_u2d_start_hc(struct usb_bus *host) +{ + int err = 0; + + /* In case the PXA3xx ULPI isn't used, do nothing. */ + if (!u2d) + return 0; + + clk_enable(u2d->clk); + + if (cpu_is_pxa310()) { + pxa310_u2d_setup_otg_hc(); + err = pxa310_start_otg_hc(host); + } + + return err; +} + +void pxa3xx_u2d_stop_hc(struct usb_bus *host) +{ + /* In case the PXA3xx ULPI isn't used, do nothing. */ + if (!u2d) + return; + + if (cpu_is_pxa310()) + pxa310_stop_otg_hc(); + + clk_disable(u2d->clk); +} + +static int pxa3xx_u2d_probe(struct platform_device *pdev) +{ + struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data; + struct resource *r; + int err; + + u2d = kzalloc(sizeof(struct pxa3xx_u2d_ulpi), GFP_KERNEL); + if (!u2d) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + u2d->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(u2d->clk)) { + dev_err(&pdev->dev, "failed to get u2d clock\n"); + err = PTR_ERR(u2d->clk); + goto err_free_mem; + } + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no IO memory resource defined\n"); + err = -ENODEV; + goto err_put_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + err = -EBUSY; + goto err_put_clk; + } + + u2d->mmio_base = ioremap(r->start, resource_size(r)); + if (!u2d->mmio_base) { + dev_err(&pdev->dev, "ioremap() failed\n"); + err = -ENODEV; + goto err_free_res; + } + + if (pdata->init) { + err = pdata->init(&pdev->dev); + if (err) + goto err_free_io; + } + + /* Only PXA310 U2D has OTG functionality */ + if (cpu_is_pxa310()) { + err = pxa310_otg_init(pdata); + if (err) + goto err_free_plat; + } + + platform_set_drvdata(pdev, &u2d); + + return 0; + +err_free_plat: + if (pdata->exit) + pdata->exit(&pdev->dev); +err_free_io: + iounmap(u2d->mmio_base); +err_free_res: + release_mem_region(r->start, resource_size(r)); +err_put_clk: + clk_put(u2d->clk); +err_free_mem: + kfree(u2d); + return err; +} + +static int pxa3xx_u2d_remove(struct platform_device *pdev) +{ + struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data; + struct resource *r; + + if (cpu_is_pxa310()) { + pxa310_stop_otg_hc(); + pxa310_otg_exit(); + } + + if (pdata->exit) + pdata->exit(&pdev->dev); + + platform_set_drvdata(pdev, NULL); + iounmap(u2d->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + + clk_put(u2d->clk); + + kfree(u2d); + + return 0; +} + +static struct platform_driver pxa3xx_u2d_ulpi_driver = { + .driver = { + .name = "pxa3xx-u2d", + .owner = THIS_MODULE, + }, + .probe = pxa3xx_u2d_probe, + .remove = pxa3xx_u2d_remove, +}; + +static int pxa3xx_u2d_ulpi_init(void) +{ + return platform_driver_register(&pxa3xx_u2d_ulpi_driver); +} +module_init(pxa3xx_u2d_ulpi_init); + +static void __exit pxa3xx_u2d_ulpi_exit(void) +{ + platform_driver_unregister(&pxa3xx_u2d_ulpi_driver); +} +module_exit(pxa3xx_u2d_ulpi_exit); + +MODULE_DESCRIPTION("PXA3xx U2D ULPI driver"); +MODULE_AUTHOR("Igor Grinberg"); +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index fa00148..c85c3a7 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -98,23 +98,6 @@ unsigned int pxa3xx_get_clk_frequency_khz(int info) return CLK / 1000; } -/* - * Return the current static memory controller clock frequency - * in units of 10kHz - */ -unsigned int pxa3xx_get_memclk_frequency_10khz(void) -{ - unsigned long acsr; - unsigned int smcfs, clk = 0; - - acsr = ACSR; - - smcfs = (acsr >> 23) & 0x7; - clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK; - - return (clk / 10000); -} - void pxa3xx_clear_reset_status(unsigned int mask) { /* RESET_STATUS_* has a 1:1 mapping with ARSR */ @@ -265,7 +248,7 @@ static struct clk_lookup pxa3xx_clkregs[] = { INIT_CLKREG(&clk_pxa3xx_i2c, "pxa2xx-i2c.0", NULL), INIT_CLKREG(&clk_pxa3xx_udc, "pxa27x-udc", NULL), INIT_CLKREG(&clk_pxa3xx_usbh, "pxa27x-ohci", NULL), - INIT_CLKREG(&clk_pxa3xx_u2d, NULL, "U2DCLK"), + INIT_CLKREG(&clk_pxa3xx_u2d, "pxa3xx-u2d", NULL), INIT_CLKREG(&clk_pxa3xx_keypad, "pxa27x-keypad", NULL), INIT_CLKREG(&clk_pxa3xx_ssp1, "pxa27x-ssp.0", NULL), INIT_CLKREG(&clk_pxa3xx_ssp2, "pxa27x-ssp.1", NULL), diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c index 0642920..7d29dd3 100644 --- a/arch/arm/mach-pxa/pxa930.c +++ b/arch/arm/mach-pxa/pxa930.c @@ -192,7 +192,7 @@ static struct mfp_addr_map pxa935_mfp_addr_map[] __initdata = { static int __init pxa930_init(void) { - if (cpu_is_pxa930() || cpu_is_pxa935()) { + if (cpu_is_pxa930() || cpu_is_pxa935() || cpu_is_pxa950()) { mfp_init_base(io_p2v(MFPR_BASE)); mfp_init_addr(pxa930_mfp_addr_map); } diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index a654d1e..62de073 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -56,6 +56,8 @@ #include "devices.h" #include "generic.h" +#define STARGATE_NR_IRQS (IRQ_BOARD_START + 8) + /* Bluetooth */ #define SG2_BT_RESET 81 @@ -1011,6 +1013,7 @@ MACHINE_START(STARGATE2, "Stargate 2") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = pxa_map_io, + .nr_irqs = STARGATE_NR_IRQS, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = stargate2_init, diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c index f02dcb5..0f440c9 100644 --- a/arch/arm/mach-pxa/tavorevb.c +++ b/arch/arm/mach-pxa/tavorevb.c @@ -25,7 +25,7 @@ #include <mach/pxa930.h> #include <mach/pxafb.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include "devices.h" #include "generic.h" diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c new file mode 100644 index 0000000..5eeba64 --- /dev/null +++ b/arch/arm/mach-pxa/tavorevb3.c @@ -0,0 +1,136 @@ +/* + * linux/arch/arm/mach-pxa/tavorevb3.c + * + * Support for the Marvell EVB3 Development Platform. + * + * Copyright: (C) Copyright 2008-2010 Marvell International Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/mfd/88pm860x.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +#include <mach/pxa930.h> + +#include <plat/i2c.h> + +#include "devices.h" +#include "generic.h" + +#define TAVOREVB3_NR_IRQS (IRQ_BOARD_START + 24) + +static mfp_cfg_t evb3_mfp_cfg[] __initdata = { + /* UART */ + GPIO53_UART1_TXD, + GPIO54_UART1_RXD, + + /* PMIC */ + PMIC_INT_GPIO83, +}; + +#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE) +static struct pm860x_touch_pdata evb3_touch = { + .gpadc_prebias = 1, + .slot_cycle = 1, + .tsi_prebias = 6, + .pen_prebias = 16, + .pen_prechg = 2, + .res_x = 300, +}; + +static struct pm860x_backlight_pdata evb3_backlight[] = { + { + .id = PM8606_ID_BACKLIGHT, + .iset = PM8606_WLED_CURRENT(24), + .flags = PM8606_BACKLIGHT1, + }, + {}, +}; + +static struct pm860x_led_pdata evb3_led[] = { + { + .id = PM8606_ID_LED, + .iset = PM8606_LED_CURRENT(12), + .flags = PM8606_LED1_RED, + }, { + .id = PM8606_ID_LED, + .iset = PM8606_LED_CURRENT(12), + .flags = PM8606_LED1_GREEN, + }, { + .id = PM8606_ID_LED, + .iset = PM8606_LED_CURRENT(12), + .flags = PM8606_LED1_BLUE, + }, { + .id = PM8606_ID_LED, + .iset = PM8606_LED_CURRENT(12), + .flags = PM8606_LED2_RED, + }, { + .id = PM8606_ID_LED, + .iset = PM8606_LED_CURRENT(12), + .flags = PM8606_LED2_GREEN, + }, { + .id = PM8606_ID_LED, + .iset = PM8606_LED_CURRENT(12), + .flags = PM8606_LED2_BLUE, + }, +}; + +static struct pm860x_platform_data evb3_pm8607_info = { + .touch = &evb3_touch, + .backlight = &evb3_backlight[0], + .led = &evb3_led[0], + .companion_addr = 0x10, + .irq_mode = 0, + .irq_base = IRQ_BOARD_START, + + .i2c_port = GI2C_PORT, +}; + +static struct i2c_board_info evb3_i2c_info[] = { + { + .type = "88PM860x", + .addr = 0x34, + .platform_data = &evb3_pm8607_info, + .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + }, +}; + +static void __init evb3_init_i2c(void) +{ + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(evb3_i2c_info)); +} +#else +static inline void evb3_init_i2c(void) {} +#endif + +static void __init evb3_init(void) +{ + /* initialize MFP configurations */ + pxa3xx_mfp_config(ARRAY_AND_SIZE(evb3_mfp_cfg)); + + pxa_set_ffuart_info(NULL); + + evb3_init_i2c(); +} + +MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)") + .phys_io = 0x40000000, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .nr_irqs = TAVOREVB3_NR_IRQS, + .init_irq = pxa3xx_init_irq, + .timer = &pxa_timer, + .init_machine = evb3_init, +MACHINE_END diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 83cc3a1..3a06e98 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -956,6 +956,7 @@ MACHINE_START(TOSA, "SHARP Tosa") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_tosa, .map_io = pxa_map_io, + .nr_irqs = TOSA_NR_IRQS, .init_irq = pxa25x_init_irq, .init_machine = tosa_init, .timer = &pxa_timer, diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index c9b747c..37d6173 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -240,6 +240,7 @@ static void __init vpac270_onenand_init(void) {} #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) static struct pxamci_platform_data vpac270_mci_platform_data = { .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .gpio_power = -1, .gpio_card_detect = GPIO53_VPAC270_SD_DETECT_N, .gpio_card_ro = GPIO52_VPAC270_SD_READONLY, .detect_delay_ms = 200, diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index f0d0228..8c44bc4 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -37,7 +37,7 @@ #include <mach/z2.h> #include <mach/pxafb.h> #include <mach/mmc.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <mach/pxa2xx_spi.h> #include <plat/i2c.h> diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index 03b9cb9..9da2b62 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -904,6 +904,7 @@ MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS") .io_pg_offst = ((io_p2v(0x40000000) >> 18) & 0xfffc), .boot_params = 0xa0000100, .map_io = zeus_map_io, + .nr_irqs = ZEUS_NR_IRQS, .init_irq = zeus_init_irq, .timer = &pxa_timer, .init_machine = zeus_init, diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index c479cbe..69df3ed 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -30,7 +30,7 @@ #include <mach/zylonite.h> #include <mach/mmc.h> #include <mach/ohci.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> #include <plat/pxa3xx_nand.h> #include "devices.h" @@ -415,6 +415,7 @@ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") .boot_params = 0xa0000100, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = pxa_map_io, + .nr_irqs = ZYLONITE_NR_IRQS, .init_irq = pxa3xx_init_irq, .timer = &pxa_timer, .init_machine = zylonite_init, diff --git a/arch/arm/mach-rpc/include/mach/vmalloc.h b/arch/arm/mach-rpc/include/mach/vmalloc.h index 9a96fd6..3bcd86f 100644 --- a/arch/arm/mach-rpc/include/mach/vmalloc.h +++ b/arch/arm/mach-rpc/include/mach/vmalloc.h @@ -7,4 +7,4 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define VMALLOC_END (PAGE_OFFSET + 0x1c000000) +#define VMALLOC_END 0xdc000000 diff --git a/arch/arm/mach-s3c64xx/dev-spi.c b/arch/arm/mach-s3c64xx/dev-spi.c index a492b98..405e621 100644 --- a/arch/arm/mach-s3c64xx/dev-spi.c +++ b/arch/arm/mach-s3c64xx/dev-spi.c @@ -18,10 +18,11 @@ #include <mach/map.h> #include <mach/gpio-bank-c.h> #include <mach/spi-clocks.h> +#include <mach/irqs.h> #include <plat/s3c64xx-spi.h> #include <plat/gpio-cfg.h> -#include <plat/irqs.h> +#include <plat/devs.h> static char *spi_src_clks[] = { [S3C64XX_SPI_SRCCLK_PCLK] = "pclk", diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index 5c07d01..e130379 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -30,73 +30,73 @@ #include <plat/devs.h> #include <plat/regs-serial.h> -#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK -#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB -#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE +#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) +#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) +#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) static struct s3c2410_uartcfg real6410_uartcfgs[] __initdata = { [0] = { - .hwport = 0, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 0, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [1] = { - .hwport = 1, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 1, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [2] = { - .hwport = 2, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [3] = { - .hwport = 3, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, + .hwport = 3, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, }; /* DM9000AEP 10/100 ethernet controller */ static struct resource real6410_dm9k_resource[] = { - [0] = { - .start = S3C64XX_PA_XM0CSN1, - .end = S3C64XX_PA_XM0CSN1 + 1, - .flags = IORESOURCE_MEM - }, - [1] = { - .start = S3C64XX_PA_XM0CSN1 + 4, - .end = S3C64XX_PA_XM0CSN1 + 5, - .flags = IORESOURCE_MEM - }, - [2] = { - .start = S3C_EINT(7), - .end = S3C_EINT(7), - .flags = IORESOURCE_IRQ, - } + [0] = { + .start = S3C64XX_PA_XM0CSN1, + .end = S3C64XX_PA_XM0CSN1 + 1, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = S3C64XX_PA_XM0CSN1 + 4, + .end = S3C64XX_PA_XM0CSN1 + 5, + .flags = IORESOURCE_MEM + }, + [2] = { + .start = S3C_EINT(7), + .end = S3C_EINT(7), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL + } }; static struct dm9000_plat_data real6410_dm9k_pdata = { - .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM), + .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM), }; static struct platform_device real6410_device_eth = { - .name = "dm9000", - .id = -1, - .num_resources = ARRAY_SIZE(real6410_dm9k_resource), - .resource = real6410_dm9k_resource, - .dev = { - .platform_data = &real6410_dm9k_pdata, - }, + .name = "dm9000", + .id = -1, + .num_resources = ARRAY_SIZE(real6410_dm9k_resource), + .resource = real6410_dm9k_resource, + .dev = { + .platform_data = &real6410_dm9k_pdata, + }, }; static struct platform_device *real6410_devices[] __initdata = { @@ -129,12 +129,12 @@ static void __init real6410_machine_init(void) /* set timing for nCS1 suitable for ethernet chip */ __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) | - (6 << S3C64XX_SROM_BCX__TACP__SHIFT) | - (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) | - (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) | - (13 << S3C64XX_SROM_BCX__TACC__SHIFT) | - (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | - (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); + (6 << S3C64XX_SROM_BCX__TACP__SHIFT) | + (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) | + (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) | + (13 << S3C64XX_SROM_BCX__TACC__SHIFT) | + (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | + (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices)); } diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig deleted file mode 100644 index 6a4af7f..0000000 --- a/arch/arm/mach-s5p6440/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -# arch/arm/mach-s5p6440/Kconfig -# -# Copyright (c) 2009 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# -# Licensed under GPLv2 - -if ARCH_S5P6440 - -config CPU_S5P6440 - bool - select S3C_PL330_DMA - help - Enable S5P6440 CPU support - -config S5P6440_SETUP_I2C1 - bool - help - Common setup code for i2c bus 1. - -config MACH_SMDK6440 - bool "SMDK6440" - select CPU_S5P6440 - select S3C_DEV_I2C1 - select S3C_DEV_RTC - select S3C_DEV_WDT - select SAMSUNG_DEV_ADC - select SAMSUNG_DEV_TS - select S5P6440_SETUP_I2C1 - help - Machine support for the Samsung SMDK6440 - -endif diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile deleted file mode 100644 index c3fe4d3..0000000 --- a/arch/arm/mach-s5p6440/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# arch/arm/mach-s5p6440/Makefile -# -# Copyright (c) 2009 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# -# Licensed under GPLv2 - -obj-y := -obj-m := -obj-n := -obj- := - -# Core support for S5P6440 system - -obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o dma.o -obj-$(CONFIG_CPU_S5P6440) += setup-i2c0.o - -# machine support - -obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o - -# device support -obj-y += dev-audio.o -obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o -obj-$(CONFIG_S5P6440_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c deleted file mode 100644 index ca6e48d..0000000 --- a/arch/arm/mach-s5p6440/clock.c +++ /dev/null @@ -1,846 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/clock.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - Clock support - * - * 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/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/sysdev.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <mach/map.h> - -#include <plat/cpu-freq.h> -#include <mach/regs-clock.h> -#include <plat/clock.h> -#include <plat/cpu.h> -#include <plat/clock-clksrc.h> -#include <plat/s5p-clock.h> -#include <plat/pll.h> -#include <plat/s5p6440.h> - -/* APLL Mux output clock */ -static struct clksrc_clk clk_mout_apll = { - .clk = { - .name = "mout_apll", - .id = -1, - }, - .sources = &clk_src_apll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 }, -}; - -static int s5p6440_epll_enable(struct clk *clk, int enable) -{ - unsigned int ctrlbit = clk->ctrlbit; - unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; - - if (enable) - __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); - else - __raw_writel(epll_con, S5P_EPLL_CON); - - return 0; -} - -static unsigned long s5p6440_epll_get_rate(struct clk *clk) -{ - return clk->rate; -} - -static u32 epll_div[][5] = { - { 36000000, 0, 48, 1, 4 }, - { 48000000, 0, 32, 1, 3 }, - { 60000000, 0, 40, 1, 3 }, - { 72000000, 0, 48, 1, 3 }, - { 84000000, 0, 28, 1, 2 }, - { 96000000, 0, 32, 1, 2 }, - { 32768000, 45264, 43, 1, 4 }, - { 45158000, 6903, 30, 1, 3 }, - { 49152000, 50332, 32, 1, 3 }, - { 67738000, 10398, 45, 1, 3 }, - { 73728000, 9961, 49, 1, 3 } -}; - -static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate) -{ - unsigned int epll_con, epll_con_k; - unsigned int i; - - if (clk->rate == rate) /* Return if nothing changed */ - return 0; - - epll_con = __raw_readl(S5P_EPLL_CON); - epll_con_k = __raw_readl(S5P_EPLL_CON_K); - - epll_con_k &= ~(PLL90XX_KDIV_MASK); - epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK); - - for (i = 0; i < ARRAY_SIZE(epll_div); i++) { - if (epll_div[i][0] == rate) { - epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT); - epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) | - (epll_div[i][3] << PLL90XX_PDIV_SHIFT) | - (epll_div[i][4] << PLL90XX_SDIV_SHIFT); - break; - } - } - - if (i == ARRAY_SIZE(epll_div)) { - printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__); - return -EINVAL; - } - - __raw_writel(epll_con, S5P_EPLL_CON); - __raw_writel(epll_con_k, S5P_EPLL_CON_K); - - clk->rate = rate; - - return 0; -} - -static struct clk_ops s5p6440_epll_ops = { - .get_rate = s5p6440_epll_get_rate, - .set_rate = s5p6440_epll_set_rate, -}; - -static struct clksrc_clk clk_mout_epll = { - .clk = { - .name = "mout_epll", - .id = -1, - }, - .sources = &clk_src_epll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 2, .size = 1 }, -}; - -static struct clksrc_clk clk_mout_mpll = { - .clk = { - .name = "mout_mpll", - .id = -1, - }, - .sources = &clk_src_mpll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 }, -}; - -enum perf_level { - L0 = 532*1000, - L1 = 266*1000, - L2 = 133*1000, -}; - -static const u32 clock_table[][3] = { - /*{ARM_CLK, DIVarm, DIVhclk}*/ - {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)}, - {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)}, - {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)}, -}; - -static unsigned long s5p6440_armclk_get_rate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - u32 clkdiv; - - /* divisor mask starts at bit0, so no need to shift */ - clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK; - - return rate / (clkdiv + 1); -} - -static unsigned long s5p6440_armclk_round_rate(struct clk *clk, - unsigned long rate) -{ - u32 iter; - - for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) { - if (rate > clock_table[iter][0]) - return clock_table[iter-1][0]; - } - - return clock_table[ARRAY_SIZE(clock_table) - 1][0]; -} - -static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate) -{ - u32 round_tmp; - u32 iter; - u32 clk_div0_tmp; - u32 cur_rate = clk->ops->get_rate(clk); - unsigned long flags; - - round_tmp = clk->ops->round_rate(clk, rate); - if (round_tmp == cur_rate) - return 0; - - - for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) { - if (round_tmp == clock_table[iter][0]) - break; - } - - if (iter >= ARRAY_SIZE(clock_table)) - iter = ARRAY_SIZE(clock_table) - 1; - - local_irq_save(flags); - if (cur_rate > round_tmp) { - /* Frequency Down */ - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); - clk_div0_tmp |= clock_table[iter][1]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & - ~(S5P_CLKDIV0_HCLK_MASK); - clk_div0_tmp |= clock_table[iter][2]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - - - } else { - /* Frequency Up */ - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & - ~(S5P_CLKDIV0_HCLK_MASK); - clk_div0_tmp |= clock_table[iter][2]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - - clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); - clk_div0_tmp |= clock_table[iter][1]; - __raw_writel(clk_div0_tmp, ARM_CLK_DIV); - } - local_irq_restore(flags); - - clk->rate = clock_table[iter][0]; - - return 0; -} - -static struct clk_ops s5p6440_clkarm_ops = { - .get_rate = s5p6440_armclk_get_rate, - .set_rate = s5p6440_armclk_set_rate, - .round_rate = s5p6440_armclk_round_rate, -}; - -static struct clksrc_clk clk_armclk = { - .clk = { - .name = "armclk", - .id = 1, - .parent = &clk_mout_apll.clk, - .ops = &s5p6440_clkarm_ops, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 }, -}; - -static struct clksrc_clk clk_dout_mpll = { - .clk = { - .name = "dout_mpll", - .id = -1, - .parent = &clk_mout_mpll.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 }, -}; - -static struct clksrc_clk clk_hclk = { - .clk = { - .name = "clk_hclk", - .id = -1, - .parent = &clk_armclk.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 }, -}; - -static struct clksrc_clk clk_pclk = { - .clk = { - .name = "clk_pclk", - .id = -1, - .parent = &clk_hclk.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 }, -}; - -static struct clk *clkset_hclklow_list[] = { - &clk_mout_apll.clk, - &clk_mout_mpll.clk, -}; - -static struct clksrc_sources clkset_hclklow = { - .sources = clkset_hclklow_list, - .nr_sources = ARRAY_SIZE(clkset_hclklow_list), -}; - -static struct clksrc_clk clk_hclk_low = { - .clk = { - .name = "hclk_low", - .id = -1, - }, - .sources = &clkset_hclklow, - .reg_src = { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 }, -}; - -static struct clksrc_clk clk_pclk_low = { - .clk = { - .name = "pclk_low", - .id = -1, - .parent = &clk_hclk_low.clk, - }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 }, -}; - -int s5p6440_clk48m_ctrl(struct clk *clk, int enable) -{ - unsigned long flags; - u32 val; - - /* can't rely on clock lock, this register has other usages */ - local_irq_save(flags); - - val = __raw_readl(S5P_OTHERS); - if (enable) - val |= S5P_OTHERS_USB_SIG_MASK; - else - val &= ~S5P_OTHERS_USB_SIG_MASK; - - __raw_writel(val, S5P_OTHERS); - - local_irq_restore(flags); - - return 0; -} - -static int s5p6440_pclk_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable); -} - -static int s5p6440_hclk0_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable); -} - -static int s5p6440_hclk1_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable); -} - -static int s5p6440_sclk_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable); -} - -static int s5p6440_sclk1_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable); -} - -static int s5p6440_mem_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable); -} - -/* - * The following clocks will be disabled during clock initialization. It is - * recommended to keep the following clocks disabled until the driver requests - * for enabling the clock. - */ -static struct clk init_clocks_disable[] = { - { - .name = "nand", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_mem_ctrl, - .ctrlbit = S5P_CLKCON_MEM0_HCLK_NFCON, - }, { - .name = "adc", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_TSADC, - }, { - .name = "i2c", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_IIC0, - }, { - .name = "i2s_v40", - .id = 0, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_IIS2, - }, { - .name = "spi", - .id = 0, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_SPI0, - }, { - .name = "spi", - .id = 1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_SPI1, - }, { - .name = "sclk_spi_48", - .id = 0, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_SPI0_48, - }, { - .name = "sclk_spi_48", - .id = 1, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_SPI1_48, - }, { - .name = "mmc_48m", - .id = 0, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_MMC0_48, - }, { - .name = "mmc_48m", - .id = 1, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_MMC1_48, - }, { - .name = "mmc_48m", - .id = 2, - .parent = &clk_48m, - .enable = s5p6440_sclk_ctrl, - .ctrlbit = S5P_CLKCON_SCLK0_MMC2_48, - }, { - .name = "otg", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_USB - }, { - .name = "post", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_POST0 - }, { - .name = "lcd", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk1_ctrl, - .ctrlbit = S5P_CLKCON_HCLK1_DISPCON, - }, { - .name = "hsmmc", - .id = 0, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_HSMMC0, - }, { - .name = "hsmmc", - .id = 1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_HSMMC1, - }, { - .name = "hsmmc", - .id = 2, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = S5P_CLKCON_HCLK0_HSMMC2, - }, { - .name = "rtc", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_RTC, - }, { - .name = "watchdog", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_WDT, - }, { - .name = "timers", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_PWM, - }, { - .name = "hclk_fimgvg", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk1_ctrl, - .ctrlbit = (1 << 2), - }, { - .name = "tsi", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk1_ctrl, - .ctrlbit = (1 << 0), - }, { - .name = "pclk_fimgvg", - .id = -1, - .parent = &clk_pclk.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 31), - }, { - .name = "dmc0", - .id = -1, - .parent = &clk_pclk.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 30), - }, { - .name = "etm", - .id = -1, - .parent = &clk_pclk.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 29), - }, { - .name = "dsim", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 28), - }, { - .name = "gps", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 25), - }, { - .name = "pcm", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = (1 << 8), - }, { - .name = "irom", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 25), - }, { - .name = "dma", - .id = -1, - .parent = &clk_hclk_low.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 12), - }, { - .name = "2d", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 8), - }, -}; - -/* - * The following clocks will be enabled during clock initialization. - */ -static struct clk init_clocks[] = { - { - .name = "gpio", - .id = -1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_GPIO, - }, { - .name = "uart", - .id = 0, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART0, - }, { - .name = "uart", - .id = 1, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART1, - }, { - .name = "uart", - .id = 2, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART2, - }, { - .name = "uart", - .id = 3, - .parent = &clk_pclk_low.clk, - .enable = s5p6440_pclk_ctrl, - .ctrlbit = S5P_CLKCON_PCLK_UART3, - }, { - .name = "mem", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 21), - }, { - .name = "intc", - .id = -1, - .parent = &clk_hclk.clk, - .enable = s5p6440_hclk0_ctrl, - .ctrlbit = (1 << 1), - }, -}; - -static struct clk clk_iis_cd_v40 = { - .name = "iis_cdclk_v40", - .id = -1, -}; - -static struct clk clk_pcm_cd = { - .name = "pcm_cdclk", - .id = -1, -}; - -static struct clk *clkset_group1_list[] = { - &clk_mout_epll.clk, - &clk_dout_mpll.clk, - &clk_fin_epll, -}; - -static struct clksrc_sources clkset_group1 = { - .sources = clkset_group1_list, - .nr_sources = ARRAY_SIZE(clkset_group1_list), -}; - -static struct clk *clkset_uart_list[] = { - &clk_mout_epll.clk, - &clk_dout_mpll.clk, -}; - -static struct clksrc_sources clkset_uart = { - .sources = clkset_uart_list, - .nr_sources = ARRAY_SIZE(clkset_uart_list), -}; - -static struct clk *clkset_audio_list[] = { - &clk_mout_epll.clk, - &clk_dout_mpll.clk, - &clk_fin_epll, - &clk_iis_cd_v40, - &clk_pcm_cd, -}; - -static struct clksrc_sources clkset_audio = { - .sources = clkset_audio_list, - .nr_sources = ARRAY_SIZE(clkset_audio_list), -}; - -static struct clksrc_clk clksrcs[] = { - { - .clk = { - .name = "mmc_bus", - .id = 0, - .ctrlbit = S5P_CLKCON_SCLK0_MMC0, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "mmc_bus", - .id = 1, - .ctrlbit = S5P_CLKCON_SCLK0_MMC1, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "mmc_bus", - .id = 2, - .ctrlbit = S5P_CLKCON_SCLK0_MMC2, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .id = -1, - .ctrlbit = S5P_CLKCON_SCLK0_UART, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "spi_epll", - .id = 0, - .ctrlbit = S5P_CLKCON_SCLK0_SPI0, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "spi_epll", - .id = 1, - .ctrlbit = S5P_CLKCON_SCLK0_SPI1, - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_post", - .id = -1, - .ctrlbit = (1 << 10), - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 }, - }, { - .clk = { - .name = "sclk_dispcon", - .id = -1, - .ctrlbit = (1 << 1), - .enable = s5p6440_sclk1_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_fimgvg", - .id = -1, - .ctrlbit = (1 << 2), - .enable = s5p6440_sclk1_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 }, - .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_audio2", - .id = -1, - .ctrlbit = (1 << 11), - .enable = s5p6440_sclk_ctrl, - }, - .sources = &clkset_audio, - .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 }, - }, -}; - -/* Clock initialisation code */ -static struct clksrc_clk *sysclks[] = { - &clk_mout_apll, - &clk_mout_epll, - &clk_mout_mpll, - &clk_dout_mpll, - &clk_armclk, - &clk_hclk, - &clk_pclk, - &clk_hclk_low, - &clk_pclk_low, -}; - -void __init_or_cpufreq s5p6440_setup_clocks(void) -{ - struct clk *xtal_clk; - unsigned long xtal; - unsigned long fclk; - unsigned long hclk; - unsigned long hclk_low; - unsigned long pclk; - unsigned long pclk_low; - unsigned long epll; - unsigned long apll; - unsigned long mpll; - unsigned int ptr; - - /* Set S5P6440 functions for clk_fout_epll */ - clk_fout_epll.enable = s5p6440_epll_enable; - clk_fout_epll.ops = &s5p6440_epll_ops; - - clk_48m.enable = s5p6440_clk48m_ctrl; - - xtal_clk = clk_get(NULL, "ext_xtal"); - BUG_ON(IS_ERR(xtal_clk)); - - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON), - __raw_readl(S5P_EPLL_CON_K)); - mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); - apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502); - - clk_fout_mpll.rate = mpll; - clk_fout_epll.rate = epll; - clk_fout_apll.rate = apll; - - printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \ - " E=%ld.%ldMHz\n", - print_mhz(apll), print_mhz(mpll), print_mhz(epll)); - - fclk = clk_get_rate(&clk_armclk.clk); - hclk = clk_get_rate(&clk_hclk.clk); - pclk = clk_get_rate(&clk_pclk.clk); - hclk_low = clk_get_rate(&clk_hclk_low.clk); - pclk_low = clk_get_rate(&clk_pclk_low.clk); - - printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ - " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n", - print_mhz(hclk), print_mhz(hclk_low), - print_mhz(pclk), print_mhz(pclk_low)); - - clk_f.rate = fclk; - clk_h.rate = hclk; - clk_p.rate = pclk; - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_set_clksrc(&clksrcs[ptr], true); -} - -static struct clk *clks[] __initdata = { - &clk_ext, - &clk_iis_cd_v40, - &clk_pcm_cd, -}; - -void __init s5p6440_register_clocks(void) -{ - struct clk *clkp; - int ret; - int ptr; - - ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); - if (ret > 0) - printk(KERN_ERR "Failed to register %u clocks\n", ret); - - for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) - s3c_register_clksrc(sysclks[ptr], 1); - - s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); - s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); - - clkp = init_clocks_disable; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - (clkp->enable)(clkp, 0); - } - - s3c_pwmclk_init(); -} diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c deleted file mode 100644 index 526f33a..0000000 --- a/arch/arm/mach-s5p6440/cpu.c +++ /dev/null @@ -1,116 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/cpu.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * 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/kernel.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/sysdev.h> -#include <linux/serial_core.h> -#include <linux/platform_device.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> - -#include <asm/proc-fns.h> - -#include <mach/hardware.h> -#include <mach/map.h> -#include <asm/irq.h> - -#include <plat/regs-serial.h> -#include <mach/regs-clock.h> - -#include <plat/cpu.h> -#include <plat/devs.h> -#include <plat/clock.h> -#include <plat/s5p6440.h> -#include <plat/adc-core.h> - -static void s5p6440_idle(void) -{ - unsigned long val; - - if (!need_resched()) { - val = __raw_readl(S5P_PWR_CFG); - val &= ~(0x3<<5); - val |= (0x1<<5); - __raw_writel(val, S5P_PWR_CFG); - - cpu_do_idle(); - } - local_irq_enable(); -} - -/* s5p6440_map_io - * - * register the standard cpu IO areas -*/ - -void __init s5p6440_map_io(void) -{ - /* initialize any device information early */ - s3c_adc_setname("s3c64xx-adc"); -} - -void __init s5p6440_init_clocks(int xtal) -{ - printk(KERN_DEBUG "%s: initializing clocks\n", __func__); - - s3c24xx_register_baseclocks(xtal); - s5p_register_clocks(xtal); - s5p6440_register_clocks(); - s5p6440_setup_clocks(); -} - -void __init s5p6440_init_irq(void) -{ - /* S5P6440 supports only 2 VIC */ - u32 vic[2]; - - /* - * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)] - * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22] - */ - vic[0] = 0xff800ae7; - vic[1] = 0xffbf23e5; - - s5p_init_irq(vic, ARRAY_SIZE(vic)); -} - -struct sysdev_class s5p6440_sysclass = { - .name = "s5p6440-core", -}; - -static struct sys_device s5p6440_sysdev = { - .cls = &s5p6440_sysclass, -}; - -static int __init s5p6440_core_init(void) -{ - return sysdev_class_register(&s5p6440_sysclass); -} - -core_initcall(s5p6440_core_init); - -int __init s5p6440_init(void) -{ - printk(KERN_INFO "S5P6440: Initializing architecture\n"); - - /* set idle function */ - pm_idle = s5p6440_idle; - - return sysdev_register(&s5p6440_sysdev); -} diff --git a/arch/arm/mach-s5p6440/dev-audio.c b/arch/arm/mach-s5p6440/dev-audio.c deleted file mode 100644 index 3ca0d2b..0000000 --- a/arch/arm/mach-s5p6440/dev-audio.c +++ /dev/null @@ -1,127 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/dev-audio.c - * - * Copyright (c) 2010 Samsung Electronics Co. Ltd - * Jaswinder Singh <jassi.brar@samsung.com> - * - * 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/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/gpio.h> - -#include <plat/gpio-cfg.h> -#include <plat/audio.h> - -#include <mach/map.h> -#include <mach/dma.h> -#include <mach/irqs.h> - -static int s5p6440_cfg_i2s(struct platform_device *pdev) -{ - /* configure GPIO for i2s port */ - switch (pdev->id) { - case -1: - s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5)); - s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5)); - break; - - default: - printk(KERN_ERR "Invalid Device %d\n", pdev->id); - return -EINVAL; - } - - return 0; -} - -static struct s3c_audio_pdata s3c_i2s_pdata = { - .cfg_gpio = s5p6440_cfg_i2s, -}; - -static struct resource s5p6440_iis0_resource[] = { - [0] = { - .start = S5P6440_PA_I2S, - .end = S5P6440_PA_I2S + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_I2S0_TX, - .end = DMACH_I2S0_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_I2S0_RX, - .end = DMACH_I2S0_RX, - .flags = IORESOURCE_DMA, - }, -}; - -struct platform_device s5p6440_device_iis = { - .name = "s3c64xx-iis-v4", - .id = -1, - .num_resources = ARRAY_SIZE(s5p6440_iis0_resource), - .resource = s5p6440_iis0_resource, - .dev = { - .platform_data = &s3c_i2s_pdata, - }, -}; - -/* PCM Controller platform_devices */ - -static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev) -{ - switch (pdev->id) { - case 0: - s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2)); - break; - - default: - printk(KERN_DEBUG "Invalid PCM Controller number!"); - return -EINVAL; - } - - return 0; -} - -static struct s3c_audio_pdata s3c_pcm_pdata = { - .cfg_gpio = s5p6440_pcm_cfg_gpio, -}; - -static struct resource s5p6440_pcm0_resource[] = { - [0] = { - .start = S5P6440_PA_PCM, - .end = S5P6440_PA_PCM + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_PCM0_TX, - .end = DMACH_PCM0_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_PCM0_RX, - .end = DMACH_PCM0_RX, - .flags = IORESOURCE_DMA, - }, -}; - -struct platform_device s5p6440_device_pcm = { - .name = "samsung-pcm", - .id = 0, - .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource), - .resource = s5p6440_pcm0_resource, - .dev = { - .platform_data = &s3c_pcm_pdata, - }, -}; diff --git a/arch/arm/mach-s5p6440/dev-spi.c b/arch/arm/mach-s5p6440/dev-spi.c deleted file mode 100644 index 510af44..0000000 --- a/arch/arm/mach-s5p6440/dev-spi.c +++ /dev/null @@ -1,176 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/dev-spi.c - * - * Copyright (C) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh <jassi.brar@samsung.com> - * - * 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/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/gpio.h> - -#include <mach/dma.h> -#include <mach/map.h> -#include <mach/irqs.h> -#include <mach/spi-clocks.h> - -#include <plat/s3c64xx-spi.h> -#include <plat/gpio-cfg.h> - -static char *spi_src_clks[] = { - [S5P6440_SPI_SRCCLK_PCLK] = "pclk", - [S5P6440_SPI_SRCCLK_SCLK] = "spi_epll", -}; - -/* SPI Controller platform_devices */ - -/* Since we emulate multi-cs capability, we do not touch the CS. - * The emulated CS is toggled by board specific mechanism, as it can - * be either some immediate GPIO or some signal out of some other - * chip in between ... or some yet another way. - * We simply do not assume anything about CS. - */ -static int s5p6440_spi_cfg_gpio(struct platform_device *pdev) -{ - switch (pdev->id) { - case 0: - s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP); - break; - - case 1: - s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2)); - s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP); - s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP); - break; - - default: - dev_err(&pdev->dev, "Invalid SPI Controller number!"); - return -EINVAL; - } - - return 0; -} - -static struct resource s5p6440_spi0_resource[] = { - [0] = { - .start = S5P6440_PA_SPI0, - .end = S5P6440_PA_SPI0 + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_SPI0_TX, - .end = DMACH_SPI0_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_SPI0_RX, - .end = DMACH_SPI0_RX, - .flags = IORESOURCE_DMA, - }, - [3] = { - .start = IRQ_SPI0, - .end = IRQ_SPI0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct s3c64xx_spi_info s5p6440_spi0_pdata = { - .cfg_gpio = s5p6440_spi_cfg_gpio, - .fifo_lvl_mask = 0x1ff, - .rx_lvl_offset = 15, -}; - -static u64 spi_dmamask = DMA_BIT_MASK(32); - -struct platform_device s5p6440_device_spi0 = { - .name = "s3c64xx-spi", - .id = 0, - .num_resources = ARRAY_SIZE(s5p6440_spi0_resource), - .resource = s5p6440_spi0_resource, - .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &s5p6440_spi0_pdata, - }, -}; - -static struct resource s5p6440_spi1_resource[] = { - [0] = { - .start = S5P6440_PA_SPI1, - .end = S5P6440_PA_SPI1 + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = DMACH_SPI1_TX, - .end = DMACH_SPI1_TX, - .flags = IORESOURCE_DMA, - }, - [2] = { - .start = DMACH_SPI1_RX, - .end = DMACH_SPI1_RX, - .flags = IORESOURCE_DMA, - }, - [3] = { - .start = IRQ_SPI1, - .end = IRQ_SPI1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct s3c64xx_spi_info s5p6440_spi1_pdata = { - .cfg_gpio = s5p6440_spi_cfg_gpio, - .fifo_lvl_mask = 0x7f, - .rx_lvl_offset = 15, -}; - -struct platform_device s5p6440_device_spi1 = { - .name = "s3c64xx-spi", - .id = 1, - .num_resources = ARRAY_SIZE(s5p6440_spi1_resource), - .resource = s5p6440_spi1_resource, - .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &s5p6440_spi1_pdata, - }, -}; - -void __init s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) -{ - struct s3c64xx_spi_info *pd; - - /* Reject invalid configuration */ - if (!num_cs || src_clk_nr < 0 - || src_clk_nr > S5P6440_SPI_SRCCLK_SCLK) { - printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__); - return; - } - - switch (cntrlr) { - case 0: - pd = &s5p6440_spi0_pdata; - break; - case 1: - pd = &s5p6440_spi1_pdata; - break; - default: - printk(KERN_ERR "%s: Invalid SPI controller(%d)\n", - __func__, cntrlr); - return; - } - - pd->num_cs = num_cs; - pd->src_clk_nr = src_clk_nr; - pd->src_clk_name = spi_src_clks[src_clk_nr]; -} diff --git a/arch/arm/mach-s5p6440/include/mach/debug-macro.S b/arch/arm/mach-s5p6440/include/mach/debug-macro.S deleted file mode 100644 index 1347d7f..0000000 --- a/arch/arm/mach-s5p6440/include/mach/debug-macro.S +++ /dev/null @@ -1,37 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/debug-macro.S - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * 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. -*/ - -/* pull in the relevant register and map files. */ - -#include <mach/map.h> -#include <plat/regs-serial.h> - - /* note, for the boot process to work we have to keep the UART - * virtual address aligned to an 1MiB boundary for the L1 - * mapping the head code makes. We keep the UART virtual address - * aligned and add in the offset when we load the value here. - */ - - .macro addruart, rx, rtmp - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 - ldreq \rx, = S3C_PA_UART - ldrne \rx, = S3C_VA_UART -#if CONFIG_DEBUG_S3C_UART != 0 - add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART) -#endif - .endm - -/* include the reset of the code which will do the work, we're only - * compiling for a single cpu processor type so the default of s3c2440 - * will be fine with us. - */ - -#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s5p6440/include/mach/gpio.h b/arch/arm/mach-s5p6440/include/mach/gpio.h deleted file mode 100644 index 2178383..0000000 --- a/arch/arm/mach-s5p6440/include/mach/gpio.h +++ /dev/null @@ -1,80 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/gpio.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - GPIO lib support - * - * 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. -*/ - -#ifndef __ASM_ARCH_GPIO_H -#define __ASM_ARCH_GPIO_H __FILE__ - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#define gpio_to_irq __gpio_to_irq - -/* GPIO bank sizes */ -#define S5P6440_GPIO_A_NR (6) -#define S5P6440_GPIO_B_NR (7) -#define S5P6440_GPIO_C_NR (8) -#define S5P6440_GPIO_F_NR (2) -#define S5P6440_GPIO_G_NR (7) -#define S5P6440_GPIO_H_NR (10) -#define S5P6440_GPIO_I_NR (16) -#define S5P6440_GPIO_J_NR (12) -#define S5P6440_GPIO_N_NR (16) -#define S5P6440_GPIO_P_NR (8) -#define S5P6440_GPIO_R_NR (15) - -/* GPIO bank numbers */ - -/* CONFIG_S3C_GPIO_SPACE allows the user to select extra - * space for debugging purposes so that any accidental - * change from one gpio bank to another can be caught. -*/ -#define S5P6440_GPIO_NEXT(__gpio) \ - ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) - -enum s5p_gpio_number { - S5P6440_GPIO_A_START = 0, - S5P6440_GPIO_B_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_A), - S5P6440_GPIO_C_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_B), - S5P6440_GPIO_F_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_C), - S5P6440_GPIO_G_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_F), - S5P6440_GPIO_H_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_G), - S5P6440_GPIO_I_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_H), - S5P6440_GPIO_J_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_I), - S5P6440_GPIO_N_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_J), - S5P6440_GPIO_P_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_N), - S5P6440_GPIO_R_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_P), -}; - -/* S5P6440 GPIO number definitions. */ -#define S5P6440_GPA(_nr) (S5P6440_GPIO_A_START + (_nr)) -#define S5P6440_GPB(_nr) (S5P6440_GPIO_B_START + (_nr)) -#define S5P6440_GPC(_nr) (S5P6440_GPIO_C_START + (_nr)) -#define S5P6440_GPF(_nr) (S5P6440_GPIO_F_START + (_nr)) -#define S5P6440_GPG(_nr) (S5P6440_GPIO_G_START + (_nr)) -#define S5P6440_GPH(_nr) (S5P6440_GPIO_H_START + (_nr)) -#define S5P6440_GPI(_nr) (S5P6440_GPIO_I_START + (_nr)) -#define S5P6440_GPJ(_nr) (S5P6440_GPIO_J_START + (_nr)) -#define S5P6440_GPN(_nr) (S5P6440_GPIO_N_START + (_nr)) -#define S5P6440_GPP(_nr) (S5P6440_GPIO_P_START + (_nr)) -#define S5P6440_GPR(_nr) (S5P6440_GPIO_R_START + (_nr)) - -/* the end of the S5P6440 specific gpios */ -#define S5P6440_GPIO_END (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1) -#define S3C_GPIO_END S5P6440_GPIO_END - -/* define the number of gpios we need to the one after the GPR() range */ -#define ARCH_NR_GPIOS (S5P6440_GPR(S5P6440_GPIO_R_NR) + \ - CONFIG_SAMSUNG_GPIO_EXTRA + 1) - -#include <asm-generic/gpio.h> - -#endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/io.h b/arch/arm/mach-s5p6440/include/mach/io.h deleted file mode 100644 index fa2d69c..0000000 --- a/arch/arm/mach-s5p6440/include/mach/io.h +++ /dev/null @@ -1,18 +0,0 @@ -/* arch/arm/mach-s5p6440/include/mach/io.h - * - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben-linux@fluff.org> - * - * Default IO routines for S3C64XX based - */ - -#ifndef __ASM_ARM_ARCH_IO_H -#define __ASM_ARM_ARCH_IO_H - -/* No current ISA/PCI bus support. */ -#define __io(a) __typesafe_io(a) -#define __mem_pci(a) (a) - -#define IO_SPACE_LIMIT (0xFFFFFFFF) - -#endif diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h deleted file mode 100644 index 6cc5cbc..0000000 --- a/arch/arm/mach-s5p6440/include/mach/map.h +++ /dev/null @@ -1,86 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/map.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - Memory map definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_MAP_H -#define __ASM_ARCH_MAP_H __FILE__ - -#include <plat/map-base.h> -#include <plat/map-s5p.h> - -#define S5P6440_PA_CHIPID (0xE0000000) -#define S5P_PA_CHIPID S5P6440_PA_CHIPID - -#define S5P6440_PA_SYSCON (0xE0100000) -#define S5P6440_PA_CLK (S5P6440_PA_SYSCON + 0x0) -#define S5P_PA_SYSCON S5P6440_PA_SYSCON - -#define S5P6440_PA_GPIO (0xE0308000) -#define S5P_PA_GPIO S5P6440_PA_GPIO - -#define S5P6440_PA_VIC0 (0xE4000000) -#define S5P_PA_VIC0 S5P6440_PA_VIC0 - -#define S5P6440_PA_PDMA 0xE9000000 - -#define S5P6440_PA_VIC1 (0xE4100000) -#define S5P_PA_VIC1 S5P6440_PA_VIC1 - -#define S5P6440_PA_TIMER (0xEA000000) -#define S5P_PA_TIMER S5P6440_PA_TIMER - -#define S5P6440_PA_RTC (0xEA100000) - -#define S5P6440_PA_WDT (0xEA200000) -#define S5P_PA_WDT S5P6440_PA_WDT - -#define S5P6440_PA_UART (0xEC000000) - -#define S5P_PA_UART0 (S5P6440_PA_UART + 0x0) -#define S5P_PA_UART1 (S5P6440_PA_UART + 0x400) -#define S5P_PA_UART2 (S5P6440_PA_UART + 0x800) -#define S5P_PA_UART3 (S5P6440_PA_UART + 0xC00) - -#define S5P_SZ_UART SZ_256 - -#define S5P6440_PA_IIC0 (0xEC104000) -#define S5P6440_PA_IIC1 (0xEC20F000) - -#define S5P6440_PA_SPI0 0xEC400000 -#define S5P6440_PA_SPI1 0xEC500000 - -#define S5P6440_PA_HSOTG (0xED100000) - -#define S5P6440_PA_HSMMC0 (0xED800000) -#define S5P6440_PA_HSMMC1 (0xED900000) -#define S5P6440_PA_HSMMC2 (0xEDA00000) - -#define S5P6440_PA_SDRAM (0x20000000) -#define S5P_PA_SDRAM S5P6440_PA_SDRAM - -/* I2S */ -#define S5P6440_PA_I2S 0xF2000000 - -/* PCM */ -#define S5P6440_PA_PCM 0xF2100000 - -#define S5P6440_PA_ADC (0xF3000000) - -/* compatibiltiy defines. */ -#define S3C_PA_UART S5P6440_PA_UART -#define S3C_PA_IIC S5P6440_PA_IIC0 -#define S3C_PA_RTC S5P6440_PA_RTC -#define S3C_PA_IIC1 S5P6440_PA_IIC1 -#define S3C_PA_WDT S5P6440_PA_WDT - -#define SAMSUNG_PA_ADC S5P6440_PA_ADC - -#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/regs-clock.h b/arch/arm/mach-s5p6440/include/mach/regs-clock.h deleted file mode 100644 index c783ecc..0000000 --- a/arch/arm/mach-s5p6440/include/mach/regs-clock.h +++ /dev/null @@ -1,130 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/regs-clock.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - Clock register definitions - * - * 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. -*/ - -#ifndef __ASM_ARCH_REGS_CLOCK_H -#define __ASM_ARCH_REGS_CLOCK_H __FILE__ - -#include <mach/map.h> - -#define S5P_CLKREG(x) (S3C_VA_SYS + (x)) - -#define S5P_APLL_LOCK S5P_CLKREG(0x00) -#define S5P_MPLL_LOCK S5P_CLKREG(0x04) -#define S5P_EPLL_LOCK S5P_CLKREG(0x08) -#define S5P_APLL_CON S5P_CLKREG(0x0C) -#define S5P_MPLL_CON S5P_CLKREG(0x10) -#define S5P_EPLL_CON S5P_CLKREG(0x14) -#define S5P_EPLL_CON_K S5P_CLKREG(0x18) -#define S5P_CLK_SRC0 S5P_CLKREG(0x1C) -#define S5P_CLK_DIV0 S5P_CLKREG(0x20) -#define S5P_CLK_DIV1 S5P_CLKREG(0x24) -#define S5P_CLK_DIV2 S5P_CLKREG(0x28) -#define S5P_CLK_OUT S5P_CLKREG(0x2C) -#define S5P_CLK_GATE_HCLK0 S5P_CLKREG(0x30) -#define S5P_CLK_GATE_PCLK S5P_CLKREG(0x34) -#define S5P_CLK_GATE_SCLK0 S5P_CLKREG(0x38) -#define S5P_CLK_GATE_MEM0 S5P_CLKREG(0x3C) -#define S5P_CLK_DIV3 S5P_CLKREG(0x40) -#define S5P_CLK_GATE_HCLK1 S5P_CLKREG(0x44) -#define S5P_CLK_GATE_SCLK1 S5P_CLKREG(0x48) -#define S5P_AHB_CON0 S5P_CLKREG(0x100) -#define S5P_CLK_SRC1 S5P_CLKREG(0x10C) -#define S5P_SWRESET S5P_CLKREG(0x114) -#define S5P_SYS_ID S5P_CLKREG(0x118) -#define S5P_SYS_OTHERS S5P_CLKREG(0x11C) -#define S5P_MEM_CFG_STAT S5P_CLKREG(0x12C) -#define S5P_PWR_CFG S5P_CLKREG(0x804) -#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0x808) -#define S5P_NORMAL_CFG S5P_CLKREG(0x810) -#define S5P_STOP_CFG S5P_CLKREG(0x814) -#define S5P_SLEEP_CFG S5P_CLKREG(0x818) -#define S5P_OSC_FREQ S5P_CLKREG(0x820) -#define S5P_OSC_STABLE S5P_CLKREG(0x824) -#define S5P_PWR_STABLE S5P_CLKREG(0x828) -#define S5P_MTC_STABLE S5P_CLKREG(0x830) -#define S5P_OTHERS S5P_CLKREG(0x900) -#define S5P_RST_STAT S5P_CLKREG(0x904) -#define S5P_WAKEUP_STAT S5P_CLKREG(0x908) -#define S5P_SLPEN S5P_CLKREG(0x930) -#define S5P_INFORM0 S5P_CLKREG(0xA00) -#define S5P_INFORM1 S5P_CLKREG(0xA04) -#define S5P_INFORM2 S5P_CLKREG(0xA08) -#define S5P_INFORM3 S5P_CLKREG(0xA0C) - -/* CLKDIV0 */ -#define S5P_CLKDIV0_PCLK_MASK (0xf << 12) -#define S5P_CLKDIV0_PCLK_SHIFT (12) -#define S5P_CLKDIV0_HCLK_MASK (0xf << 8) -#define S5P_CLKDIV0_HCLK_SHIFT (8) -#define S5P_CLKDIV0_MPLL_MASK (0x1 << 4) -#define S5P_CLKDIV0_ARM_MASK (0xf << 0) -#define S5P_CLKDIV0_ARM_SHIFT (0) - -/* CLKDIV3 */ -#define S5P_CLKDIV3_PCLK_LOW_MASK (0xf << 12) -#define S5P_CLKDIV3_PCLK_LOW_SHIFT (12) -#define S5P_CLKDIV3_HCLK_LOW_MASK (0xf << 8) -#define S5P_CLKDIV3_HCLK_LOW_SHIFT (8) - -/* HCLK0 GATE Registers */ -#define S5P_CLKCON_HCLK0_USB (1<<20) -#define S5P_CLKCON_HCLK0_HSMMC2 (1<<19) -#define S5P_CLKCON_HCLK0_HSMMC1 (1<<18) -#define S5P_CLKCON_HCLK0_HSMMC0 (1<<17) -#define S5P_CLKCON_HCLK0_POST0 (1<<5) - -/* HCLK1 GATE Registers */ -#define S5P_CLKCON_HCLK1_DISPCON (1<<1) - -/* PCLK GATE Registers */ -#define S5P_CLKCON_PCLK_IIS2 (1<<26) -#define S5P_CLKCON_PCLK_SPI1 (1<<22) -#define S5P_CLKCON_PCLK_SPI0 (1<<21) -#define S5P_CLKCON_PCLK_GPIO (1<<18) -#define S5P_CLKCON_PCLK_IIC0 (1<<17) -#define S5P_CLKCON_PCLK_TSADC (1<<12) -#define S5P_CLKCON_PCLK_PWM (1<<7) -#define S5P_CLKCON_PCLK_RTC (1<<6) -#define S5P_CLKCON_PCLK_WDT (1<<5) -#define S5P_CLKCON_PCLK_UART3 (1<<4) -#define S5P_CLKCON_PCLK_UART2 (1<<3) -#define S5P_CLKCON_PCLK_UART1 (1<<2) -#define S5P_CLKCON_PCLK_UART0 (1<<1) - -/* SCLK0 GATE Registers */ -#define S5P_CLKCON_SCLK0_MMC2_48 (1<<29) -#define S5P_CLKCON_SCLK0_MMC1_48 (1<<28) -#define S5P_CLKCON_SCLK0_MMC0_48 (1<<27) -#define S5P_CLKCON_SCLK0_MMC2 (1<<26) -#define S5P_CLKCON_SCLK0_MMC1 (1<<25) -#define S5P_CLKCON_SCLK0_MMC0 (1<<24) -#define S5P_CLKCON_SCLK0_SPI1_48 (1<<23) -#define S5P_CLKCON_SCLK0_SPI0_48 (1<<22) -#define S5P_CLKCON_SCLK0_SPI1 (1<<21) -#define S5P_CLKCON_SCLK0_SPI0 (1<<20) -#define S5P_CLKCON_SCLK0_UART (1<<5) - -/* SCLK1 GATE Registers */ - -/* MEM0 GATE Registers */ -#define S5P_CLKCON_MEM0_HCLK_NFCON (1<<2) - -/*OTHERS Resgister */ -#define S5P_OTHERS_USB_SIG_MASK (1<<16) -#define S5P_OTHERS_HCLK_LOW_SEL_MPLL (1<<6) - -/* Compatibility defines */ -#define ARM_CLK_DIV S5P_CLK_DIV0 -#define ARM_DIV_RATIO_SHIFT 0 -#define ARM_DIV_MASK (0xf << ARM_DIV_RATIO_SHIFT) - -#endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h b/arch/arm/mach-s5p6440/include/mach/spi-clocks.h deleted file mode 100644 index 5fbca50..0000000 --- a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h +++ /dev/null @@ -1,17 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/spi-clocks.h - * - * Copyright (C) 2010 Samsung Electronics Co. Ltd. - * Jaswinder Singh <jassi.brar@samsung.com> - * - * 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. - */ - -#ifndef __S5P6440_PLAT_SPI_CLKS_H -#define __S5P6440_PLAT_SPI_CLKS_H __FILE__ - -#define S5P6440_SPI_SRCCLK_PCLK 0 -#define S5P6440_SPI_SRCCLK_SCLK 1 - -#endif /* __S5P6440_PLAT_SPI_CLKS_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/uncompress.h b/arch/arm/mach-s5p6440/include/mach/uncompress.h deleted file mode 100644 index 7c1f600..0000000 --- a/arch/arm/mach-s5p6440/include/mach/uncompress.h +++ /dev/null @@ -1,24 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/uncompress.h - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - uncompress code - * - * 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. -*/ - -#ifndef __ASM_ARCH_UNCOMPRESS_H -#define __ASM_ARCH_UNCOMPRESS_H - -#include <mach/map.h> -#include <plat/uncompress.h> - -static void arch_detect_cpu(void) -{ - /* we do not need to do any cpu detection here at the moment. */ -} - -#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s5p6440/init.c b/arch/arm/mach-s5p6440/init.c deleted file mode 100644 index a1f3727..0000000 --- a/arch/arm/mach-s5p6440/init.c +++ /dev/null @@ -1,52 +0,0 @@ -/* linux/arch/arm/mach-s5p6440/init.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * S5P6440 - Init support - * - * 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/kernel.h> -#include <linux/types.h> -#include <linux/init.h> -#include <linux/serial_core.h> - -#include <plat/cpu.h> -#include <plat/devs.h> -#include <plat/s5p6440.h> -#include <plat/regs-serial.h> - -static struct s3c24xx_uart_clksrc s5p6440_serial_clocks[] = { - [0] = { - .name = "pclk_low", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "uclk1", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, -}; - -/* uart registration process */ -void __init s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - struct s3c2410_uartcfg *tcfg = cfg; - u32 ucnt; - - for (ucnt = 0; ucnt < no; ucnt++, tcfg++) { - if (!tcfg->clocks) { - tcfg->clocks = s5p6440_serial_clocks; - tcfg->clocks_size = ARRAY_SIZE(s5p6440_serial_clocks); - } - } - - s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); -} diff --git a/arch/arm/mach-s5p6442/cpu.c b/arch/arm/mach-s5p6442/cpu.c index a48fb55..842af86 100644 --- a/arch/arm/mach-s5p6442/cpu.c +++ b/arch/arm/mach-s5p6442/cpu.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-s5p6442/cpu.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * http://www.samsung.com * * 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 @@ -19,6 +19,7 @@ #include <linux/sysdev.h> #include <linux/serial_core.h> #include <linux/platform_device.h> +#include <linux/sched.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -47,10 +48,30 @@ static struct map_desc s5p6442_iodesc[] __initdata = { .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5P6442_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5P6442_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5P6442_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)VA_VIC2, .pfn = __phys_to_pfn(S5P6442_PA_VIC2), .length = SZ_16K, .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, + .type = MT_DEVICE, } }; @@ -62,10 +83,11 @@ static void s5p6442_idle(void) local_irq_enable(); } -/* s5p6442_map_io +/* + * s5p6442_map_io * * register the standard cpu IO areas -*/ + */ void __init s5p6442_map_io(void) { diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h index 281d256..31fb2e6 100644 --- a/arch/arm/mach-s5p6442/include/mach/map.h +++ b/arch/arm/mach-s5p6442/include/mach/map.h @@ -23,16 +23,10 @@ #define S5P_PA_SYSCON S5P6442_PA_SYSCON #define S5P6442_PA_GPIO (0xE0200000) -#define S5P_PA_GPIO S5P6442_PA_GPIO #define S5P6442_PA_VIC0 (0xE4000000) -#define S5P_PA_VIC0 S5P6442_PA_VIC0 - #define S5P6442_PA_VIC1 (0xE4100000) -#define S5P_PA_VIC1 S5P6442_PA_VIC1 - #define S5P6442_PA_VIC2 (0xE4200000) -#define S5P_PA_VIC2 S5P6442_PA_VIC2 #define S5P6442_PA_MDMA 0xE8000000 #define S5P6442_PA_PDMA 0xE9000000 diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig new file mode 100644 index 0000000..fbcae93 --- /dev/null +++ b/arch/arm/mach-s5p64x0/Kconfig @@ -0,0 +1,57 @@ +# arch/arm/mach-s5p64x0/Kconfig +# +# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. +# http://www.samsung.com/ +# +# Licensed under GPLv2 + +if ARCH_S5P64X0 + +config CPU_S5P6440 + bool + select PLAT_S5P + select S3C_PL330_DMA + help + Enable S5P6440 CPU support + +config CPU_S5P6450 + bool + select PLAT_S5P + select S3C_PL330_DMA + help + Enable S5P6450 CPU support + +config S5P64X0_SETUP_I2C1 + bool + help + Common setup code for i2c bus 1. + +# machine support + +config MACH_SMDK6440 + bool "SMDK6440" + select CPU_S5P6440 + select S3C_DEV_I2C1 + select S3C_DEV_RTC + select S3C_DEV_WDT + select S3C64XX_DEV_SPI + select SAMSUNG_DEV_ADC + select SAMSUNG_DEV_TS + select S5P64X0_SETUP_I2C1 + help + Machine support for the Samsung SMDK6440 + +config MACH_SMDK6450 + bool "SMDK6450" + select CPU_S5P6450 + select S3C_DEV_I2C1 + select S3C_DEV_RTC + select S3C_DEV_WDT + select S3C64XX_DEV_SPI + select SAMSUNG_DEV_ADC + select SAMSUNG_DEV_TS + select S5P64X0_SETUP_I2C1 + help + Machine support for the Samsung SMDK6450 + +endif diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile new file mode 100644 index 0000000..2655829 --- /dev/null +++ b/arch/arm/mach-s5p64x0/Makefile @@ -0,0 +1,30 @@ +# arch/arm/mach-s5p64x0/Makefile +# +# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. +# http://www.samsung.com +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for S5P64X0 system + +obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o clock.o dma.o +obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o +obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o gpio.o +obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o + +# machine support + +obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o +obj-$(CONFIG_MACH_SMDK6450) += mach-smdk6450.o + +# device support + +obj-y += dev-audio.o +obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o + +obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/mach-s5p6440/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot index ff90aa1..ff90aa1 100644 --- a/arch/arm/mach-s5p6440/Makefile.boot +++ b/arch/arm/mach-s5p64x0/Makefile.boot diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c new file mode 100644 index 0000000..f93dcd8 --- /dev/null +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c @@ -0,0 +1,626 @@ +/* linux/arch/arm/mach-s5p64x0/clock-s5p6440.c + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P6440 - Clock support + * + * 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/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/s5p64x0-clock.h> + +#include <plat/cpu-freq.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> +#include <plat/s5p-clock.h> +#include <plat/clock-clksrc.h> +#include <plat/s5p6440.h> + +static u32 epll_div[][5] = { + { 36000000, 0, 48, 1, 4 }, + { 48000000, 0, 32, 1, 3 }, + { 60000000, 0, 40, 1, 3 }, + { 72000000, 0, 48, 1, 3 }, + { 84000000, 0, 28, 1, 2 }, + { 96000000, 0, 32, 1, 2 }, + { 32768000, 45264, 43, 1, 4 }, + { 45158000, 6903, 30, 1, 3 }, + { 49152000, 50332, 32, 1, 3 }, + { 67738000, 10398, 45, 1, 3 }, + { 73728000, 9961, 49, 1, 3 } +}; + +static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + + if (clk->rate == rate) /* Return if nothing changed */ + return 0; + + epll_con = __raw_readl(S5P64X0_EPLL_CON); + epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K); + + epll_con_k &= ~(PLL90XX_KDIV_MASK); + epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT); + epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) | + (epll_div[i][3] << PLL90XX_PDIV_SHIFT) | + (epll_div[i][4] << PLL90XX_SDIV_SHIFT); + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__); + return -EINVAL; + } + + __raw_writel(epll_con, S5P64X0_EPLL_CON); + __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops s5p6440_epll_ops = { + .get_rate = s5p64x0_epll_get_rate, + .set_rate = s5p6440_epll_set_rate, +}; + +static struct clksrc_clk clk_hclk = { + .clk = { + .name = "clk_hclk", + .id = -1, + .parent = &clk_armclk.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk = { + .clk = { + .name = "clk_pclk", + .id = -1, + .parent = &clk_hclk.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 }, +}; +static struct clksrc_clk clk_hclk_low = { + .clk = { + .name = "clk_hclk_low", + .id = -1, + }, + .sources = &clkset_hclk_low, + .reg_src = { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk_low = { + .clk = { + .name = "clk_pclk_low", + .id = -1, + .parent = &clk_hclk_low.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 }, +}; + +/* + * The following clocks will be disabled during clock initialization. It is + * recommended to keep the following clocks disabled until the driver requests + * for enabling the clock. + */ +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_mem_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "post", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 5) + }, { + .name = "2d", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 18), + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 19), + }, { + .name = "otg", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 20) + }, { + .name = "irom", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "lcd", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "hclk_fimgvg", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "tsi", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "rtc", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "timers", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "pcm", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "adc", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "i2c", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "spi", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "spi", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "gps", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "i2s_v40", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 26), + }, { + .name = "dsim", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 28), + }, { + .name = "etm", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 29), + }, { + .name = "dmc0", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 30), + }, { + .name = "pclk_fimgvg", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 31), + }, { + .name = "sclk_spi_48", + .id = 0, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "sclk_spi_48", + .id = 1, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 23), + }, { + .name = "mmc_48m", + .id = 0, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 27), + }, { + .name = "mmc_48m", + .id = 1, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 28), + }, { + .name = "mmc_48m", + .id = 2, + .parent = &clk_48m, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 29), + }, +}; + +/* + * The following clocks will be enabled during clock initialization. + */ +static struct clk init_clocks[] = { + { + .name = "intc", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "mem", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "dma", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "uart", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "uart", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "uart", + .id = 2, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "uart", + .id = 3, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "gpio", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 18), + }, +}; + +static struct clk clk_iis_cd_v40 = { + .name = "iis_cdclk_v40", + .id = -1, +}; + +static struct clk clk_pcm_cd = { + .name = "pcm_cdclk", + .id = -1, +}; + +static struct clk *clkset_group1_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll.clk, + &clk_fin_epll, +}; + +static struct clksrc_sources clkset_group1 = { + .sources = clkset_group1_list, + .nr_sources = ARRAY_SIZE(clkset_group1_list), +}; + +static struct clk *clkset_uart_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll.clk, +}; + +static struct clksrc_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static struct clk *clkset_audio_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll.clk, + &clk_fin_epll, + &clk_iis_cd_v40, + &clk_pcm_cd, +}; + +static struct clksrc_sources clkset_audio = { + .sources = clkset_audio_list, + .nr_sources = ARRAY_SIZE(clkset_audio_list), +}; + +static struct clksrc_clk clksrcs[] = { + { + .clk = { + .name = "mmc_bus", + .id = 0, + .ctrlbit = (1 << 24), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "mmc_bus", + .id = 1, + .ctrlbit = (1 << 25), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "mmc_bus", + .id = 2, + .ctrlbit = (1 << 26), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = -1, + .ctrlbit = (1 << 5), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_uart, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 0, + .ctrlbit = (1 << 20), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 1, + .ctrlbit = (1 << 21), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_post", + .id = -1, + .ctrlbit = (1 << 10), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_dispcon", + .id = -1, + .ctrlbit = (1 << 1), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimgvg", + .id = -1, + .ctrlbit = (1 << 2), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_audio2", + .id = -1, + .ctrlbit = (1 << 11), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_audio, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 }, + }, +}; + +/* Clock initialization code */ +static struct clksrc_clk *sysclks[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_dout_mpll, + &clk_armclk, + &clk_hclk, + &clk_pclk, + &clk_hclk_low, + &clk_pclk_low, +}; + +void __init_or_cpufreq s5p6440_setup_clocks(void) +{ + struct clk *xtal_clk; + + unsigned long xtal; + unsigned long fclk; + unsigned long hclk; + unsigned long hclk_low; + unsigned long pclk; + unsigned long pclk_low; + + unsigned long apll; + unsigned long mpll; + unsigned long epll; + unsigned int ptr; + + /* Set S5P6440 functions for clk_fout_epll */ + + clk_fout_epll.enable = s5p64x0_epll_enable; + clk_fout_epll.ops = &s5p6440_epll_ops; + + clk_48m.enable = s5p64x0_clk48m_ctrl; + + xtal_clk = clk_get(NULL, "ext_xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502); + mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502); + epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON), + __raw_readl(S5P64X0_EPLL_CON_K)); + + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + + printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \ + " E=%ld.%ldMHz\n", + print_mhz(apll), print_mhz(mpll), print_mhz(epll)); + + fclk = clk_get_rate(&clk_armclk.clk); + hclk = clk_get_rate(&clk_hclk.clk); + pclk = clk_get_rate(&clk_pclk.clk); + hclk_low = clk_get_rate(&clk_hclk_low.clk); + pclk_low = clk_get_rate(&clk_pclk_low.clk); + + printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ + " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n", + print_mhz(hclk), print_mhz(hclk_low), + print_mhz(pclk), print_mhz(pclk_low)); + + clk_f.rate = fclk; + clk_h.rate = hclk; + clk_p.rate = pclk; + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_set_clksrc(&clksrcs[ptr], true); +} + +static struct clk *clks[] __initdata = { + &clk_ext, + &clk_iis_cd_v40, + &clk_pcm_cd, +}; + +void __init s5p6440_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); + + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); + s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c new file mode 100644 index 0000000..f9afb05 --- /dev/null +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c @@ -0,0 +1,655 @@ +/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P6450 - Clock support + * + * 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/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/s5p64x0-clock.h> + +#include <plat/cpu-freq.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> +#include <plat/s5p-clock.h> +#include <plat/clock-clksrc.h> +#include <plat/s5p6450.h> + +static struct clksrc_clk clk_mout_dpll = { + .clk = { + .name = "mout_dpll", + .id = -1, + }, + .sources = &clk_src_dpll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 }, +}; + +static u32 epll_div[][5] = { + { 133000000, 27307, 55, 2, 2 }, + { 100000000, 43691, 41, 2, 2 }, + { 480000000, 0, 80, 2, 0 }, +}; + +static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + + if (clk->rate == rate) /* Return if nothing changed */ + return 0; + + epll_con = __raw_readl(S5P64X0_EPLL_CON); + epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K); + + epll_con_k &= ~(PLL90XX_KDIV_MASK); + epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT); + epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) | + (epll_div[i][3] << PLL90XX_PDIV_SHIFT) | + (epll_div[i][4] << PLL90XX_SDIV_SHIFT); + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__); + return -EINVAL; + } + + __raw_writel(epll_con, S5P64X0_EPLL_CON); + __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops s5p6450_epll_ops = { + .get_rate = s5p64x0_epll_get_rate, + .set_rate = s5p6450_epll_set_rate, +}; + +static struct clksrc_clk clk_dout_epll = { + .clk = { + .name = "dout_epll", + .id = -1, + .parent = &clk_mout_epll.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 }, +}; + +static struct clksrc_clk clk_mout_hclk_sel = { + .clk = { + .name = "mout_hclk_sel", + .id = -1, + }, + .sources = &clkset_hclk_low, + .reg_src = { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 }, +}; + +static struct clk *clkset_hclk_list[] = { + &clk_mout_hclk_sel.clk, + &clk_armclk.clk, +}; + +static struct clksrc_sources clkset_hclk = { + .sources = clkset_hclk_list, + .nr_sources = ARRAY_SIZE(clkset_hclk_list), +}; + +static struct clksrc_clk clk_hclk = { + .clk = { + .name = "clk_hclk", + .id = -1, + }, + .sources = &clkset_hclk, + .reg_src = { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk = { + .clk = { + .name = "clk_pclk", + .id = -1, + .parent = &clk_hclk.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 }, +}; +static struct clksrc_clk clk_dout_pwm_ratio0 = { + .clk = { + .name = "clk_dout_pwm_ratio0", + .id = -1, + .parent = &clk_mout_hclk_sel.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk_to_wdt_pwm = { + .clk = { + .name = "clk_pclk_to_wdt_pwm", + .id = -1, + .parent = &clk_dout_pwm_ratio0.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 }, +}; + +static struct clksrc_clk clk_hclk_low = { + .clk = { + .name = "clk_hclk_low", + .id = -1, + }, + .sources = &clkset_hclk_low, + .reg_src = { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clk_pclk_low = { + .clk = { + .name = "clk_pclk_low", + .id = -1, + .parent = &clk_hclk_low.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 }, +}; + +/* + * The following clocks will be disabled during clock initialization. It is + * recommended to keep the following clocks disabled until the driver requests + * for enabling the clock. + */ +static struct clk init_clocks_disable[] = { + { + .name = "usbhost", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 18), + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 19), + }, { + .name = "usbotg", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 20), + }, { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s5p64x0_hclk1_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "adc", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "i2c", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 17), + }, { + .name = "spi", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "spi", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 22), + }, { + .name = "iis", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 26), + }, { + .name = "i2c", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 27), + }, { + .name = "dmc0", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 30), + } +}; + +/* + * The following clocks will be enabled during clock initialization. + */ +static struct clk init_clocks[] = { + { + .name = "intc", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "mem", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "dma", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p64x0_hclk0_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "uart", + .id = 0, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "uart", + .id = 1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "uart", + .id = 2, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "uart", + .id = 3, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "timers", + .id = -1, + .parent = &clk_pclk_to_wdt_pwm.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "gpio", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p64x0_pclk_ctrl, + .ctrlbit = (1 << 18), + }, +}; + +static struct clk *clkset_uart_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, +}; + +static struct clksrc_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static struct clk *clkset_mali_list[] = { + &clk_mout_epll.clk, + &clk_mout_apll.clk, + &clk_mout_mpll.clk, +}; + +static struct clksrc_sources clkset_mali = { + .sources = clkset_mali_list, + .nr_sources = ARRAY_SIZE(clkset_mali_list), +}; + +static struct clk *clkset_group2_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, + &clk_ext_xtal_mux, +}; + +static struct clksrc_sources clkset_group2 = { + .sources = clkset_group2_list, + .nr_sources = ARRAY_SIZE(clkset_group2_list), +}; + +static struct clk *clkset_dispcon_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, + &clk_ext_xtal_mux, + &clk_mout_dpll.clk, +}; + +static struct clksrc_sources clkset_dispcon = { + .sources = clkset_dispcon_list, + .nr_sources = ARRAY_SIZE(clkset_dispcon_list), +}; + +static struct clk *clkset_hsmmc44_list[] = { + &clk_dout_epll.clk, + &clk_dout_mpll.clk, + &clk_ext_xtal_mux, + &s5p_clk_27m, + &clk_48m, +}; + +static struct clksrc_sources clkset_hsmmc44 = { + .sources = clkset_hsmmc44_list, + .nr_sources = ARRAY_SIZE(clkset_hsmmc44_list), +}; + +static struct clk *clkset_sclk_audio0_list[] = { + [0] = &clk_dout_epll.clk, + [1] = &clk_dout_mpll.clk, + [2] = &clk_ext_xtal_mux, + [3] = NULL, + [4] = NULL, +}; + +static struct clksrc_sources clkset_sclk_audio0 = { + .sources = clkset_sclk_audio0_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list), +}; + +static struct clksrc_clk clk_sclk_audio0 = { + .clk = { + .name = "audio-bus", + .id = -1, + .enable = s5p64x0_sclk_ctrl, + .ctrlbit = (1 << 8), + .parent = &clk_dout_epll.clk, + }, + .sources = &clkset_sclk_audio0, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 }, +}; + +static struct clksrc_clk clksrcs[] = { + { + .clk = { + .name = "sclk_mmc", + .id = 0, + .ctrlbit = (1 << 24), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 1, + .ctrlbit = (1 << 25), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 2, + .ctrlbit = (1 << 26), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = -1, + .ctrlbit = (1 << 5), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_uart, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 0, + .ctrlbit = (1 << 20), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 1, + .ctrlbit = (1 << 21), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = -1, + .ctrlbit = (1 << 10), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "aclk_mali", + .id = -1, + .ctrlbit = (1 << 2), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_mali, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_2d", + .id = -1, + .ctrlbit = (1 << 12), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_mali, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_usi", + .id = -1, + .ctrlbit = (1 << 7), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_camif", + .id = -1, + .ctrlbit = (1 << 6), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_dispcon", + .id = -1, + .ctrlbit = (1 << 1), + .enable = s5p64x0_sclk1_ctrl, + }, + .sources = &clkset_dispcon, + .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_hsmmc44", + .id = -1, + .ctrlbit = (1 << 30), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_hsmmc44, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 }, + }, +}; + +/* Clock initialization code */ +static struct clksrc_clk *sysclks[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_dout_epll, + &clk_mout_mpll, + &clk_dout_mpll, + &clk_armclk, + &clk_mout_hclk_sel, + &clk_dout_pwm_ratio0, + &clk_pclk_to_wdt_pwm, + &clk_hclk, + &clk_pclk, + &clk_hclk_low, + &clk_pclk_low, + &clk_sclk_audio0, +}; + +void __init_or_cpufreq s5p6450_setup_clocks(void) +{ + struct clk *xtal_clk; + + unsigned long xtal; + unsigned long fclk; + unsigned long hclk; + unsigned long hclk_low; + unsigned long pclk; + unsigned long pclk_low; + + unsigned long apll; + unsigned long mpll; + unsigned long epll; + unsigned long dpll; + unsigned int ptr; + + /* Set S5P6450 functions for clk_fout_epll */ + + clk_fout_epll.enable = s5p64x0_epll_enable; + clk_fout_epll.ops = &s5p6450_epll_ops; + + clk_48m.enable = s5p64x0_clk48m_ctrl; + + xtal_clk = clk_get(NULL, "ext_xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502); + mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502); + epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON), + __raw_readl(S5P64X0_EPLL_CON_K)); + dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON), + __raw_readl(S5P6450_DPLL_CON_K), pll_4650c); + + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_dpll.rate = dpll; + + printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \ + " E=%ld.%ldMHz, D=%ld.%ldMHz\n", + print_mhz(apll), print_mhz(mpll), print_mhz(epll), + print_mhz(dpll)); + + fclk = clk_get_rate(&clk_armclk.clk); + hclk = clk_get_rate(&clk_hclk.clk); + pclk = clk_get_rate(&clk_pclk.clk); + hclk_low = clk_get_rate(&clk_hclk_low.clk); + pclk_low = clk_get_rate(&clk_pclk_low.clk); + + printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ + " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n", + print_mhz(hclk), print_mhz(hclk_low), + print_mhz(pclk), print_mhz(pclk_low)); + + clk_f.rate = fclk; + clk_h.rate = hclk; + clk_p.rate = pclk; + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_set_clksrc(&clksrcs[ptr], true); +} + +void __init s5p6450_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); + s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c new file mode 100644 index 0000000..523ba80 --- /dev/null +++ b/arch/arm/mach-s5p64x0/clock.c @@ -0,0 +1,253 @@ +/* linux/arch/arm/mach-s5p64x0/clock.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Clock support + * + * 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/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> + +#include <plat/cpu-freq.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> +#include <plat/s5p-clock.h> +#include <plat/clock-clksrc.h> +#include <plat/s5p6440.h> +#include <plat/s5p6450.h> + +struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .sources = &clk_src_apll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 0, .size = 1 }, +}; + +struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .sources = &clk_src_mpll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 1, .size = 1 }, +}; + +struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .sources = &clk_src_epll, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 2, .size = 1 }, +}; + +enum perf_level { + L0 = 532*1000, + L1 = 266*1000, + L2 = 133*1000, +}; + +static const u32 clock_table[][3] = { + /*{ARM_CLK, DIVarm, DIVhclk}*/ + {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, + {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, + {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, +}; + +int s5p64x0_epll_enable(struct clk *clk, int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + unsigned int epll_con = __raw_readl(S5P64X0_EPLL_CON) & ~ctrlbit; + + if (enable) + __raw_writel(epll_con | ctrlbit, S5P64X0_EPLL_CON); + else + __raw_writel(epll_con, S5P64X0_EPLL_CON); + + return 0; +} + +unsigned long s5p64x0_epll_get_rate(struct clk *clk) +{ + return clk->rate; +} + +unsigned long s5p64x0_armclk_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + u32 clkdiv; + + /* divisor mask starts at bit0, so no need to shift */ + clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK; + + return rate / (clkdiv + 1); +} + +unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate) +{ + u32 iter; + + for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) { + if (rate > clock_table[iter][0]) + return clock_table[iter-1][0]; + } + + return clock_table[ARRAY_SIZE(clock_table) - 1][0]; +} + +int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate) +{ + u32 round_tmp; + u32 iter; + u32 clk_div0_tmp; + u32 cur_rate = clk->ops->get_rate(clk); + unsigned long flags; + + round_tmp = clk->ops->round_rate(clk, rate); + if (round_tmp == cur_rate) + return 0; + + + for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) { + if (round_tmp == clock_table[iter][0]) + break; + } + + if (iter >= ARRAY_SIZE(clock_table)) + iter = ARRAY_SIZE(clock_table) - 1; + + local_irq_save(flags); + if (cur_rate > round_tmp) { + /* Frequency Down */ + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); + clk_div0_tmp |= clock_table[iter][1]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & + ~(S5P64X0_CLKDIV0_HCLK_MASK); + clk_div0_tmp |= clock_table[iter][2]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + + + } else { + /* Frequency Up */ + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & + ~(S5P64X0_CLKDIV0_HCLK_MASK); + clk_div0_tmp |= clock_table[iter][2]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + + clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK); + clk_div0_tmp |= clock_table[iter][1]; + __raw_writel(clk_div0_tmp, ARM_CLK_DIV); + } + local_irq_restore(flags); + + clk->rate = clock_table[iter][0]; + + return 0; +} + +struct clk_ops s5p64x0_clkarm_ops = { + .get_rate = s5p64x0_armclk_get_rate, + .set_rate = s5p64x0_armclk_set_rate, + .round_rate = s5p64x0_armclk_round_rate, +}; + +struct clksrc_clk clk_armclk = { + .clk = { + .name = "armclk", + .id = 1, + .parent = &clk_mout_apll.clk, + .ops = &s5p64x0_clkarm_ops, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 0, .size = 4 }, +}; + +struct clksrc_clk clk_dout_mpll = { + .clk = { + .name = "dout_mpll", + .id = -1, + .parent = &clk_mout_mpll.clk, + }, + .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 4, .size = 1 }, +}; + +struct clk *clkset_hclk_low_list[] = { + &clk_mout_apll.clk, + &clk_mout_mpll.clk, +}; + +struct clksrc_sources clkset_hclk_low = { + .sources = clkset_hclk_low_list, + .nr_sources = ARRAY_SIZE(clkset_hclk_low_list), +}; + +int s5p64x0_pclk_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_PCLK, clk, enable); +} + +int s5p64x0_hclk0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK0, clk, enable); +} + +int s5p64x0_hclk1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK1, clk, enable); +} + +int s5p64x0_sclk_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK0, clk, enable); +} + +int s5p64x0_sclk1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK1, clk, enable); +} + +int s5p64x0_mem_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P64X0_CLK_GATE_MEM0, clk, enable); +} + +int s5p64x0_clk48m_ctrl(struct clk *clk, int enable) +{ + unsigned long flags; + u32 val; + + /* can't rely on clock lock, this register has other usages */ + local_irq_save(flags); + + val = __raw_readl(S5P64X0_OTHERS); + if (enable) + val |= S5P64X0_OTHERS_USB_SIG_MASK; + else + val &= ~S5P64X0_OTHERS_USB_SIG_MASK; + + __raw_writel(val, S5P64X0_OTHERS); + + local_irq_restore(flags); + + return 0; +} diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c new file mode 100644 index 0000000..b8d02eb --- /dev/null +++ b/arch/arm/mach-s5p64x0/cpu.c @@ -0,0 +1,209 @@ +/* linux/arch/arm/mach-s5p64x0/cpu.c + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * 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/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/sysdev.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/sched.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/proc-fns.h> +#include <asm/irq.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> + +#include <plat/regs-serial.h> +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> +#include <plat/s5p6440.h> +#include <plat/s5p6450.h> +#include <plat/adc-core.h> + +/* Initial IO mappings */ + +static struct map_desc s5p64x0_iodesc[] __initdata = { + { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5P64X0_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5P64X0_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5P64X0_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, +}; + +static struct map_desc s5p6440_iodesc[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S5P6440_PA_UART(0)), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static struct map_desc s5p6450_iodesc[] __initdata = { + { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S5P6450_PA_UART(0)), + .length = SZ_512K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S3C_VA_UART + SZ_512K, + .pfn = __phys_to_pfn(S5P6450_PA_UART(5)), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static void s5p64x0_idle(void) +{ + unsigned long val; + + if (!need_resched()) { + val = __raw_readl(S5P64X0_PWR_CFG); + val &= ~(0x3 << 5); + val |= (0x1 << 5); + __raw_writel(val, S5P64X0_PWR_CFG); + + cpu_do_idle(); + } + local_irq_enable(); +} + +/* + * s5p64x0_map_io + * + * register the standard CPU IO areas + */ + +void __init s5p6440_map_io(void) +{ + /* initialize any device information early */ + s3c_adc_setname("s3c64xx-adc"); + + iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); + iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc)); +} + +void __init s5p6450_map_io(void) +{ + /* initialize any device information early */ + s3c_adc_setname("s3c64xx-adc"); + + iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); + iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6440_iodesc)); +} + +/* + * s5p64x0_init_clocks + * + * register and setup the CPU clocks + */ + +void __init s5p6440_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initializing clocks\n", __func__); + + s3c24xx_register_baseclocks(xtal); + s5p_register_clocks(xtal); + s5p6440_register_clocks(); + s5p6440_setup_clocks(); +} + +void __init s5p6450_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initializing clocks\n", __func__); + + s3c24xx_register_baseclocks(xtal); + s5p_register_clocks(xtal); + s5p6450_register_clocks(); + s5p6450_setup_clocks(); +} + +/* + * s5p64x0_init_irq + * + * register the CPU interrupts + */ + +void __init s5p6440_init_irq(void) +{ + /* S5P6440 supports 2 VIC */ + u32 vic[2]; + + /* + * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)] + * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22] + */ + vic[0] = 0xff800ae7; + vic[1] = 0xffbf23e5; + + s5p_init_irq(vic, ARRAY_SIZE(vic)); +} + +void __init s5p6450_init_irq(void) +{ + /* S5P6450 supports only 2 VIC */ + u32 vic[2]; + + /* + * VIC0 is missing IRQ_VIC0[(13-15), (21-22)] + * VIC1 is missing IRQ VIC1[12, 14, 23] + */ + vic[0] = 0xff9f1fff; + vic[1] = 0xff7fafff; + + s5p_init_irq(vic, ARRAY_SIZE(vic)); +} + +struct sysdev_class s5p64x0_sysclass = { + .name = "s5p64x0-core", +}; + +static struct sys_device s5p64x0_sysdev = { + .cls = &s5p64x0_sysclass, +}; + +static int __init s5p64x0_core_init(void) +{ + return sysdev_class_register(&s5p64x0_sysclass); +} +core_initcall(s5p64x0_core_init); + +int __init s5p64x0_init(void) +{ + printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n"); + + /* set idle function */ + pm_idle = s5p64x0_idle; + + return sysdev_register(&s5p64x0_sysdev); +} diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c new file mode 100644 index 0000000..fa097bd --- /dev/null +++ b/arch/arm/mach-s5p64x0/dev-audio.c @@ -0,0 +1,164 @@ +/* linux/arch/arm/mach-s5p64x0/dev-audio.c + * + * Copyright (c) 2010 Samsung Electronics Co. Ltd + * Jaswinder Singh <jassi.brar@samsung.com> + * + * 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/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/gpio.h> + +#include <plat/gpio-cfg.h> +#include <plat/audio.h> + +#include <mach/map.h> +#include <mach/dma.h> +#include <mach/irqs.h> + +static int s5p6440_cfg_i2s(struct platform_device *pdev) +{ + /* configure GPIO for i2s port */ + switch (pdev->id) { + case -1: + s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5)); + break; + + default: + printk(KERN_ERR "Invalid Device %d\n", pdev->id); + return -EINVAL; + } + + return 0; +} + +static int s5p6450_cfg_i2s(struct platform_device *pdev) +{ + /* configure GPIO for i2s port */ + switch (pdev->id) { + case -1: + s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6450_GPR(4), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6450_GPR(5), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6450_GPR(6), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6450_GPR(7), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6450_GPR(8), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6450_GPR(13), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6450_GPR(14), S3C_GPIO_SFN(5)); + break; + + default: + printk(KERN_ERR "Invalid Device %d\n", pdev->id); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s5p6440_i2s_pdata = { + .cfg_gpio = s5p6440_cfg_i2s, +}; + +static struct s3c_audio_pdata s5p6450_i2s_pdata = { + .cfg_gpio = s5p6450_cfg_i2s, +}; + +static struct resource s5p64x0_iis0_resource[] = { + [0] = { + .start = S5P64X0_PA_I2S, + .end = S5P64X0_PA_I2S + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S0_TX, + .end = DMACH_I2S0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S0_RX, + .end = DMACH_I2S0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6440_device_iis = { + .name = "s3c64xx-iis-v4", + .id = -1, + .num_resources = ARRAY_SIZE(s5p64x0_iis0_resource), + .resource = s5p64x0_iis0_resource, + .dev = { + .platform_data = &s5p6440_i2s_pdata, + }, +}; + +struct platform_device s5p6450_device_iis0 = { + .name = "s3c64xx-iis-v4", + .id = -1, + .num_resources = ARRAY_SIZE(s5p64x0_iis0_resource), + .resource = s5p64x0_iis0_resource, + .dev = { + .platform_data = &s5p6450_i2s_pdata, + }, +}; + +/* PCM Controller platform_devices */ + +static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2)); + break; + + default: + printk(KERN_DEBUG "Invalid PCM Controller number!"); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s5p6440_pcm_pdata = { + .cfg_gpio = s5p6440_pcm_cfg_gpio, +}; + +static struct resource s5p6440_pcm0_resource[] = { + [0] = { + .start = S5P64X0_PA_PCM, + .end = S5P64X0_PA_PCM + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM0_TX, + .end = DMACH_PCM0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM0_RX, + .end = DMACH_PCM0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6440_device_pcm = { + .name = "samsung-pcm", + .id = 0, + .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource), + .resource = s5p6440_pcm0_resource, + .dev = { + .platform_data = &s5p6440_pcm_pdata, + }, +}; diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c new file mode 100644 index 0000000..5b69ec4 --- /dev/null +++ b/arch/arm/mach-s5p64x0/dev-spi.c @@ -0,0 +1,232 @@ +/* linux/arch/arm/mach-s5p64x0/dev-spi.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh <jassi.brar@samsung.com> + * + * 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/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/gpio.h> + +#include <mach/dma.h> +#include <mach/map.h> +#include <mach/irqs.h> +#include <mach/regs-clock.h> +#include <mach/spi-clocks.h> + +#include <plat/s3c64xx-spi.h> +#include <plat/gpio-cfg.h> + +static char *s5p64x0_spi_src_clks[] = { + [S5P64X0_SPI_SRCCLK_PCLK] = "pclk", + [S5P64X0_SPI_SRCCLK_SCLK] = "sclk_spi", +}; + +/* SPI Controller platform_devices */ + +/* Since we emulate multi-cs capability, we do not touch the CS. + * The emulated CS is toggled by board specific mechanism, as it can + * be either some immediate GPIO or some signal out of some other + * chip in between ... or some yet another way. + * We simply do not assume anything about CS. + */ +static int s5p6440_spi_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP); + break; + + case 1: + s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP); + break; + + default: + dev_err(&pdev->dev, "Invalid SPI Controller number!"); + return -EINVAL; + } + + return 0; +} + +static int s5p6450_spi_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin(S5P6450_GPC(0), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6450_GPC(1), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6450_GPC(2), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5P6450_GPC(0), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6450_GPC(1), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6450_GPC(2), S3C_GPIO_PULL_UP); + break; + + case 1: + s3c_gpio_cfgpin(S5P6450_GPC(4), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6450_GPC(5), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6450_GPC(6), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5P6450_GPC(4), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6450_GPC(5), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S5P6450_GPC(6), S3C_GPIO_PULL_UP); + break; + + default: + dev_err(&pdev->dev, "Invalid SPI Controller number!"); + return -EINVAL; + } + + return 0; +} + +static struct resource s5p64x0_spi0_resource[] = { + [0] = { + .start = S5P64X0_PA_SPI0, + .end = S5P64X0_PA_SPI0 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPI0_TX, + .end = DMACH_SPI0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_SPI0_RX, + .end = DMACH_SPI0_RX, + .flags = IORESOURCE_DMA, + }, + [3] = { + .start = IRQ_SPI0, + .end = IRQ_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c64xx_spi_info s5p6440_spi0_pdata = { + .cfg_gpio = s5p6440_spi_cfg_gpio, + .fifo_lvl_mask = 0x1ff, + .rx_lvl_offset = 15, +}; + +static struct s3c64xx_spi_info s5p6450_spi0_pdata = { + .cfg_gpio = s5p6450_spi_cfg_gpio, + .fifo_lvl_mask = 0x1ff, + .rx_lvl_offset = 15, +}; + +static u64 spi_dmamask = DMA_BIT_MASK(32); + +struct platform_device s5p64x0_device_spi0 = { + .name = "s3c64xx-spi", + .id = 0, + .num_resources = ARRAY_SIZE(s5p64x0_spi0_resource), + .resource = s5p64x0_spi0_resource, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +static struct resource s5p64x0_spi1_resource[] = { + [0] = { + .start = S5P64X0_PA_SPI1, + .end = S5P64X0_PA_SPI1 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPI1_TX, + .end = DMACH_SPI1_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_SPI1_RX, + .end = DMACH_SPI1_RX, + .flags = IORESOURCE_DMA, + }, + [3] = { + .start = IRQ_SPI1, + .end = IRQ_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c64xx_spi_info s5p6440_spi1_pdata = { + .cfg_gpio = s5p6440_spi_cfg_gpio, + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 15, +}; + +static struct s3c64xx_spi_info s5p6450_spi1_pdata = { + .cfg_gpio = s5p6450_spi_cfg_gpio, + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 15, +}; + +struct platform_device s5p64x0_device_spi1 = { + .name = "s3c64xx-spi", + .id = 1, + .num_resources = ARRAY_SIZE(s5p64x0_spi1_resource), + .resource = s5p64x0_spi1_resource, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) +{ + unsigned int id; + struct s3c64xx_spi_info *pd; + + id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000; + + /* Reject invalid configuration */ + if (!num_cs || src_clk_nr < 0 + || src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) { + printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__); + return; + } + + switch (cntrlr) { + case 0: + if (id == 0x50000) + pd = &s5p6450_spi0_pdata; + else + pd = &s5p6440_spi0_pdata; + + s5p64x0_device_spi0.dev.platform_data = pd; + break; + case 1: + if (id == 0x50000) + pd = &s5p6450_spi1_pdata; + else + pd = &s5p6440_spi1_pdata; + + s5p64x0_device_spi1.dev.platform_data = pd; + break; + default: + printk(KERN_ERR "%s: Invalid SPI controller(%d)\n", + __func__, cntrlr); + return; + } + + pd->num_cs = num_cs; + pd->src_clk_nr = src_clk_nr; + pd->src_clk_name = s5p64x0_spi_src_clks[src_clk_nr]; +} diff --git a/arch/arm/mach-s5p6440/dma.c b/arch/arm/mach-s5p64x0/dma.c index 07606ad..29a8c24 100644 --- a/arch/arm/mach-s5p6440/dma.c +++ b/arch/arm/mach-s5p64x0/dma.c @@ -1,4 +1,8 @@ -/* +/* linux/arch/arm/mach-s5p64x0/dma.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * * Copyright (C) 2010 Samsung Electronics Co. Ltd. * Jaswinder Singh <jassi.brar@samsung.com> * @@ -15,26 +19,25 @@ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ +*/ #include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <plat/devs.h> -#include <plat/irqs.h> - #include <mach/map.h> #include <mach/irqs.h> +#include <mach/regs-clock.h> +#include <plat/devs.h> #include <plat/s3c-pl330-pdata.h> static u64 dma_dmamask = DMA_BIT_MASK(32); -static struct resource s5p6440_pdma_resource[] = { +static struct resource s5p64x0_pdma_resource[] = { [0] = { - .start = S5P6440_PA_PDMA, - .end = S5P6440_PA_PDMA + SZ_4K, - .flags = IORESOURCE_MEM, + .start = S5P64X0_PA_PDMA, + .end = S5P64X0_PA_PDMA + SZ_4K, + .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_DMA0, @@ -80,26 +83,67 @@ static struct s3c_pl330_platdata s5p6440_pdma_pdata = { }, }; -static struct platform_device s5p6440_device_pdma = { +static struct s3c_pl330_platdata s5p6450_pdma_pdata = { + .peri = { + [0] = DMACH_UART0_RX, + [1] = DMACH_UART0_TX, + [2] = DMACH_UART1_RX, + [3] = DMACH_UART1_TX, + [4] = DMACH_UART2_RX, + [5] = DMACH_UART2_TX, + [6] = DMACH_UART3_RX, + [7] = DMACH_UART3_TX, + [8] = DMACH_UART4_RX, + [9] = DMACH_UART4_TX, + [10] = DMACH_PCM0_TX, + [11] = DMACH_PCM0_RX, + [12] = DMACH_I2S0_TX, + [13] = DMACH_I2S0_RX, + [14] = DMACH_SPI0_TX, + [15] = DMACH_SPI0_RX, + [16] = DMACH_PCM1_TX, + [17] = DMACH_PCM1_RX, + [18] = DMACH_PCM2_TX, + [19] = DMACH_PCM2_RX, + [20] = DMACH_SPI1_TX, + [21] = DMACH_SPI1_RX, + [22] = DMACH_USI_TX, + [23] = DMACH_USI_RX, + [24] = DMACH_MAX, + [25] = DMACH_I2S1_TX, + [26] = DMACH_I2S1_RX, + [27] = DMACH_I2S2_TX, + [28] = DMACH_I2S2_RX, + [29] = DMACH_PWM, + [30] = DMACH_UART5_RX, + [31] = DMACH_UART5_TX, + }, +}; + +static struct platform_device s5p64x0_device_pdma = { .name = "s3c-pl330", - .id = 1, - .num_resources = ARRAY_SIZE(s5p6440_pdma_resource), - .resource = s5p6440_pdma_resource, + .id = 0, + .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource), + .resource = s5p64x0_pdma_resource, .dev = { .dma_mask = &dma_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &s5p6440_pdma_pdata, }, }; -static struct platform_device *s5p6440_dmacs[] __initdata = { - &s5p6440_device_pdma, -}; - -static int __init s5p6440_dma_init(void) +static int __init s5p64x0_dma_init(void) { - platform_add_devices(s5p6440_dmacs, ARRAY_SIZE(s5p6440_dmacs)); + unsigned int id; + + id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000; + + if (id == 0x50000) + s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata; + else + s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata; + + platform_device_register(&s5p64x0_device_pdma); return 0; } -arch_initcall(s5p6440_dma_init); +arch_initcall(s5p64x0_dma_init); diff --git a/arch/arm/mach-s5p6440/gpio.c b/arch/arm/mach-s5p64x0/gpio.c index 8bf6e0c..39159dd 100644 --- a/arch/arm/mach-s5p6440/gpio.c +++ b/arch/arm/mach-s5p64x0/gpio.c @@ -1,14 +1,14 @@ -/* arch/arm/mach-s5p6440/gpio.c +/* linux/arch/arm/mach-s5p64x0/gpio.c * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - GPIOlib support + * S5P64X0 - GPIOlib support * * 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/kernel.h> #include <linux/irq.h> @@ -22,26 +22,29 @@ #include <plat/gpio-cfg.h> #include <plat/gpio-cfg-helpers.h> -/* GPIO bank summary: -* -* Bank GPIOs Style SlpCon ExtInt Group -* A 6 4Bit Yes 1 -* B 7 4Bit Yes 1 -* C 8 4Bit Yes 2 -* F 2 2Bit Yes 4 [1] -* G 7 4Bit Yes 5 -* H 10 4Bit[2] Yes 6 -* I 16 2Bit Yes None -* J 12 2Bit Yes None -* N 16 2Bit No IRQ_EINT -* P 8 2Bit Yes 8 -* R 15 4Bit[2] Yes 8 -* -* [1] BANKF pins 14,15 do not form part of the external interrupt sources -* [2] BANK has two control registers, GPxCON0 and GPxCON1 -*/ +/* To be implemented S5P6450 GPIO */ + +/* + * S5P6440 GPIO bank summary: + * + * Bank GPIOs Style SlpCon ExtInt Group + * A 6 4Bit Yes 1 + * B 7 4Bit Yes 1 + * C 8 4Bit Yes 2 + * F 2 2Bit Yes 4 [1] + * G 7 4Bit Yes 5 + * H 10 4Bit[2] Yes 6 + * I 16 2Bit Yes None + * J 12 2Bit Yes None + * N 16 2Bit No IRQ_EINT + * P 8 2Bit Yes 8 + * R 15 4Bit[2] Yes 8 + * + * [1] BANKF pins 14,15 do not form part of the external interrupt sources + * [2] BANK has two control registers, GPxCON0 and GPxCON1 + */ -static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, +static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, unsigned int offset) { struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); @@ -77,7 +80,7 @@ static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip, return 0; } -static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, +static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, unsigned int offset, int value) { struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); @@ -124,12 +127,11 @@ static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip, return 0; } -int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, +int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, unsigned int off, unsigned int cfg) { void __iomem *reg = chip->base; unsigned int shift; - unsigned long flags; u32 con; switch (off) { @@ -155,26 +157,22 @@ int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip, cfg <<= shift; } - s3c_gpio_lock(chip, flags); - con = __raw_readl(reg); con &= ~(0xf << shift); con |= cfg; __raw_writel(con, reg); - s3c_gpio_unlock(chip, flags); - return 0; } -static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = { +static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = { { .cfg_eint = 0, }, { .cfg_eint = 7, }, { .cfg_eint = 3, - .set_config = s5p6440_gpio_setcfg_4bit_rbank, + .set_config = s5p64x0_gpio_setcfg_4bit_rbank, }, { .cfg_eint = 0, .set_config = s3c_gpio_setcfg_s3c24xx, @@ -193,7 +191,7 @@ static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = { static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { { .base = S5P6440_GPA_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPA(0), .ngpio = S5P6440_GPIO_A_NR, @@ -201,7 +199,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { }, }, { .base = S5P6440_GPB_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPB(0), .ngpio = S5P6440_GPIO_B_NR, @@ -209,7 +207,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { }, }, { .base = S5P6440_GPC_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPC(0), .ngpio = S5P6440_GPIO_C_NR, @@ -217,7 +215,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { }, }, { .base = S5P6440_GPG_BASE, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPG(0), .ngpio = S5P6440_GPIO_G_NR, @@ -229,7 +227,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = { static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = { { .base = S5P6440_GPH_BASE + 0x4, - .config = &s5p6440_gpio_cfgs[1], + .config = &s5p64x0_gpio_cfgs[1], .chip = { .base = S5P6440_GPH(0), .ngpio = S5P6440_GPIO_H_NR, @@ -238,10 +236,10 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = { }, }; -static struct s3c_gpio_chip gpio_rbank_4bit2[] = { +static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = { { .base = S5P6440_GPR_BASE + 0x4, - .config = &s5p6440_gpio_cfgs[2], + .config = &s5p64x0_gpio_cfgs[2], .chip = { .base = S5P6440_GPR(0), .ngpio = S5P6440_GPIO_R_NR, @@ -253,7 +251,7 @@ static struct s3c_gpio_chip gpio_rbank_4bit2[] = { static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { { .base = S5P6440_GPF_BASE, - .config = &s5p6440_gpio_cfgs[5], + .config = &s5p64x0_gpio_cfgs[5], .chip = { .base = S5P6440_GPF(0), .ngpio = S5P6440_GPIO_F_NR, @@ -261,7 +259,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPI_BASE, - .config = &s5p6440_gpio_cfgs[3], + .config = &s5p64x0_gpio_cfgs[3], .chip = { .base = S5P6440_GPI(0), .ngpio = S5P6440_GPIO_I_NR, @@ -269,7 +267,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPJ_BASE, - .config = &s5p6440_gpio_cfgs[3], + .config = &s5p64x0_gpio_cfgs[3], .chip = { .base = S5P6440_GPJ(0), .ngpio = S5P6440_GPIO_J_NR, @@ -277,7 +275,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPN_BASE, - .config = &s5p6440_gpio_cfgs[4], + .config = &s5p64x0_gpio_cfgs[4], .chip = { .base = S5P6440_GPN(0), .ngpio = S5P6440_GPIO_N_NR, @@ -285,7 +283,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }, { .base = S5P6440_GPP_BASE, - .config = &s5p6440_gpio_cfgs[5], + .config = &s5p64x0_gpio_cfgs[5], .chip = { .base = S5P6440_GPP(0), .ngpio = S5P6440_GPIO_P_NR, @@ -294,7 +292,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = { }, }; -void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) +void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) { for (; nr_chips > 0; nr_chips--, chipcfg++) { if (!chipcfg->set_config) @@ -308,13 +306,13 @@ void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) } } -static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, +static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip, int nr_chips) { for (; nr_chips > 0; nr_chips--, chip++) { - chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input; + chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input; chip->chip.direction_output = - s5p6440_gpiolib_rbank_4bit2_output; + s5p64x0_gpiolib_rbank_4bit2_output; s3c_gpiolib_add(chip); } } @@ -324,8 +322,8 @@ static int __init s5p6440_gpiolib_init(void) struct s3c_gpio_chip *chips = s5p6440_gpio_2bit; int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit); - s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs, - ARRAY_SIZE(s5p6440_gpio_cfgs)); + s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs, + ARRAY_SIZE(s5p64x0_gpio_cfgs)); for (; nr_chips > 0; nr_chips--, chips++) s3c_gpiolib_add(chips); @@ -336,8 +334,8 @@ static int __init s5p6440_gpiolib_init(void) samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2, ARRAY_SIZE(s5p6440_gpio_4bit2)); - s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2, - ARRAY_SIZE(gpio_rbank_4bit2)); + s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2, + ARRAY_SIZE(s5p6440_gpio_rbank_4bit2)); return 0; } diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S new file mode 100644 index 0000000..79b04e6 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S @@ -0,0 +1,33 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/debug-macro.S + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * 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. +*/ + +/* pull in the relevant register and map files. */ + +#include <plat/map-base.h> +#include <plat/map-s5p.h> + +#include <plat/regs-serial.h> + + .macro addruart, rp, rv + mov \rp, #0xE0000000 + orr \rp, \rp, #0x00100000 + ldr \rp, [\rp, #0x118 ] + and \rp, \rp, #0xff000 + teq \rp, #0x50000 @@ S5P6450 + ldreq \rp, =0xEC800000 + movne \rp, #0xEC000000 @@ S5P6440 + ldrne \rv, = S3C_VA_UART +#if CONFIG_DEBUG_S3C_UART != 0 + add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART) + add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART) +#endif + .endm + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s5p6440/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h index 81209eb..81209eb 100644 --- a/arch/arm/mach-s5p6440/include/mach/dma.h +++ b/arch/arm/mach-s5p64x0/include/mach/dma.h diff --git a/arch/arm/mach-s5p6440/include/mach/entry-macro.S b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S index e65f1b9..10b62b4 100644 --- a/arch/arm/mach-s5p6440/include/mach/entry-macro.S +++ b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/entry-macro.S +/* linux/arch/arm/mach-s5p64x0/include/mach/entry-macro.S * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * Low-level IRQ helper macros for the Samsung S5P6440 + * Low-level IRQ helper macros for the Samsung S5P64X0 * * 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/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h new file mode 100644 index 0000000..5486c8f --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/gpio.h @@ -0,0 +1,139 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/gpio.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - GPIO lib support + * + * 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. +*/ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H __FILE__ + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +/* GPIO bank sizes */ + +#define S5P6440_GPIO_A_NR (6) +#define S5P6440_GPIO_B_NR (7) +#define S5P6440_GPIO_C_NR (8) +#define S5P6440_GPIO_F_NR (2) +#define S5P6440_GPIO_G_NR (7) +#define S5P6440_GPIO_H_NR (10) +#define S5P6440_GPIO_I_NR (16) +#define S5P6440_GPIO_J_NR (12) +#define S5P6440_GPIO_N_NR (16) +#define S5P6440_GPIO_P_NR (8) +#define S5P6440_GPIO_R_NR (15) + +#define S5P6450_GPIO_A_NR (6) +#define S5P6450_GPIO_B_NR (7) +#define S5P6450_GPIO_C_NR (8) +#define S5P6450_GPIO_D_NR (8) +#define S5P6450_GPIO_F_NR (2) +#define S5P6450_GPIO_G_NR (14) +#define S5P6450_GPIO_H_NR (10) +#define S5P6450_GPIO_I_NR (16) +#define S5P6450_GPIO_J_NR (12) +#define S5P6450_GPIO_K_NR (5) +#define S5P6450_GPIO_N_NR (16) +#define S5P6450_GPIO_P_NR (11) +#define S5P6450_GPIO_Q_NR (14) +#define S5P6450_GPIO_R_NR (15) +#define S5P6450_GPIO_S_NR (8) + +/* GPIO bank numbers */ + +/* CONFIG_S3C_GPIO_SPACE allows the user to select extra + * space for debugging purposes so that any accidental + * change from one gpio bank to another can be caught. +*/ + +#define S5P64X0_GPIO_NEXT(__gpio) \ + ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) + +enum s5p6440_gpio_number { + S5P6440_GPIO_A_START = 0, + S5P6440_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_A), + S5P6440_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_B), + S5P6440_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_C), + S5P6440_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_F), + S5P6440_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_G), + S5P6440_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_H), + S5P6440_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_I), + S5P6440_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_J), + S5P6440_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_N), + S5P6440_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_P), +}; + +enum s5p6450_gpio_number { + S5P6450_GPIO_A_START = 0, + S5P6450_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_A), + S5P6450_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_B), + S5P6450_GPIO_D_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_C), + S5P6450_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_D), + S5P6450_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_F), + S5P6450_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_G), + S5P6450_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_H), + S5P6450_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_I), + S5P6450_GPIO_K_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_J), + S5P6450_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_K), + S5P6450_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_N), + S5P6450_GPIO_Q_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_P), + S5P6450_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_Q), + S5P6450_GPIO_S_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_R), +}; + +/* GPIO number definitions */ + +#define S5P6440_GPA(_nr) (S5P6440_GPIO_A_START + (_nr)) +#define S5P6440_GPB(_nr) (S5P6440_GPIO_B_START + (_nr)) +#define S5P6440_GPC(_nr) (S5P6440_GPIO_C_START + (_nr)) +#define S5P6440_GPF(_nr) (S5P6440_GPIO_F_START + (_nr)) +#define S5P6440_GPG(_nr) (S5P6440_GPIO_G_START + (_nr)) +#define S5P6440_GPH(_nr) (S5P6440_GPIO_H_START + (_nr)) +#define S5P6440_GPI(_nr) (S5P6440_GPIO_I_START + (_nr)) +#define S5P6440_GPJ(_nr) (S5P6440_GPIO_J_START + (_nr)) +#define S5P6440_GPN(_nr) (S5P6440_GPIO_N_START + (_nr)) +#define S5P6440_GPP(_nr) (S5P6440_GPIO_P_START + (_nr)) +#define S5P6440_GPR(_nr) (S5P6440_GPIO_R_START + (_nr)) + +#define S5P6450_GPA(_nr) (S5P6450_GPIO_A_START + (_nr)) +#define S5P6450_GPB(_nr) (S5P6450_GPIO_B_START + (_nr)) +#define S5P6450_GPC(_nr) (S5P6450_GPIO_C_START + (_nr)) +#define S5P6450_GPD(_nr) (S5P6450_GPIO_D_START + (_nr)) +#define S5P6450_GPF(_nr) (S5P6450_GPIO_F_START + (_nr)) +#define S5P6450_GPG(_nr) (S5P6450_GPIO_G_START + (_nr)) +#define S5P6450_GPH(_nr) (S5P6450_GPIO_H_START + (_nr)) +#define S5P6450_GPI(_nr) (S5P6450_GPIO_I_START + (_nr)) +#define S5P6450_GPJ(_nr) (S5P6450_GPIO_J_START + (_nr)) +#define S5P6450_GPK(_nr) (S5P6450_GPIO_K_START + (_nr)) +#define S5P6450_GPN(_nr) (S5P6450_GPIO_N_START + (_nr)) +#define S5P6450_GPP(_nr) (S5P6450_GPIO_P_START + (_nr)) +#define S5P6450_GPQ(_nr) (S5P6450_GPIO_Q_START + (_nr)) +#define S5P6450_GPR(_nr) (S5P6450_GPIO_R_START + (_nr)) +#define S5P6450_GPS(_nr) (S5P6450_GPIO_S_START + (_nr)) + +/* the end of the S5P64X0 specific gpios */ + +#define S5P6440_GPIO_END (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1) +#define S5P6450_GPIO_END (S5P6450_GPS(S5P6450_GPIO_S_NR) + 1) + +#define S5P64X0_GPIO_END (S5P6440_GPIO_END > S5P6450_GPIO_END ? \ + S5P6440_GPIO_END : S5P6450_GPIO_END) + +#define S3C_GPIO_END S5P64X0_GPIO_END + +/* define the number of gpios we need to the one after the last GPIO range */ + +#define ARCH_NR_GPIOS (S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA) + +#include <asm-generic/gpio.h> + +#endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/hardware.h b/arch/arm/mach-s5p64x0/include/mach/hardware.h index be8b26e..d3e8799 100644 --- a/arch/arm/mach-s5p6440/include/mach/hardware.h +++ b/arch/arm/mach-s5p64x0/include/mach/hardware.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/hardware.h +/* linux/arch/arm/mach-s5p64x0/include/mach/hardware.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - Hardware support + * S5P64X0 - Hardware support * * 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/arch/arm/mach-s5p64x0/include/mach/i2c.h b/arch/arm/mach-s5p64x0/include/mach/i2c.h new file mode 100644 index 0000000..887d252 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/i2c.h @@ -0,0 +1,17 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/i2c.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 I2C configuration + * + * 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. +*/ + +extern void s5p6440_i2c0_cfg_gpio(struct platform_device *dev); +extern void s5p6440_i2c1_cfg_gpio(struct platform_device *dev); + +extern void s5p6450_i2c0_cfg_gpio(struct platform_device *dev); +extern void s5p6450_i2c1_cfg_gpio(struct platform_device *dev); diff --git a/arch/arm/mach-s5p64x0/include/mach/io.h b/arch/arm/mach-s5p64x0/include/mach/io.h new file mode 100644 index 0000000..a3e095c --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/io.h @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/io.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Copyright 2008 Simtec Electronics + * Ben Dooks <ben-linux@fluff.org> + * + * Default IO routines for S5P64X0 based + * + * 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. +*/ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* No current ISA/PCI bus support. */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#define IO_SPACE_LIMIT (0xFFFFFFFF) + +#endif diff --git a/arch/arm/mach-s5p6440/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h index 16a7612..513abff 100644 --- a/arch/arm/mach-s5p6440/include/mach/irqs.h +++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h @@ -1,17 +1,17 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/irqs.h +/* linux/arch/arm/mach-s5p64x0/include/mach/irqs.h * - * Copyright 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - IRQ definitions + * S5P64X0 - IRQ definitions * * 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. */ -#ifndef __ASM_ARCH_S5P_IRQS_H -#define __ASM_ARCH_S5P_IRQS_H __FILE__ +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H __FILE__ #include <plat/irqs.h> @@ -20,10 +20,12 @@ #define IRQ_EINT0_3 S5P_IRQ_VIC0(0) #define IRQ_EINT4_11 S5P_IRQ_VIC0(1) #define IRQ_RTC_TIC S5P_IRQ_VIC0(2) +#define IRQ_IIS1 S5P_IRQ_VIC0(3) /* for only S5P6450 */ +#define IRQ_IIS2 S5P_IRQ_VIC0(4) /* for only S5P6450 */ #define IRQ_IIC1 S5P_IRQ_VIC0(5) #define IRQ_I2SV40 S5P_IRQ_VIC0(6) -#define IRQ_GPS S5P_IRQ_VIC0(7) -#define IRQ_POST0 S5P_IRQ_VIC0(9) +#define IRQ_GPS S5P_IRQ_VIC0(7) /* for only S5P6450 */ + #define IRQ_2D S5P_IRQ_VIC0(11) #define IRQ_TIMER0_VIC S5P_IRQ_VIC0(23) #define IRQ_TIMER1_VIC S5P_IRQ_VIC0(24) @@ -39,22 +41,26 @@ #define IRQ_EINT12_15 S5P_IRQ_VIC1(0) #define IRQ_PCM0 S5P_IRQ_VIC1(2) +#define IRQ_PCM1 S5P_IRQ_VIC1(3) /* for only S5P6450 */ +#define IRQ_PCM2 S5P_IRQ_VIC1(4) /* for only S5P6450 */ #define IRQ_UART0 S5P_IRQ_VIC1(5) #define IRQ_UART1 S5P_IRQ_VIC1(6) #define IRQ_UART2 S5P_IRQ_VIC1(7) #define IRQ_UART3 S5P_IRQ_VIC1(8) #define IRQ_DMA0 S5P_IRQ_VIC1(9) +#define IRQ_UART4 S5P_IRQ_VIC1(10) /* S5P6450 */ +#define IRQ_UART5 S5P_IRQ_VIC1(11) /* S5P6450 */ #define IRQ_NFC S5P_IRQ_VIC1(13) +#define IRQ_USI S5P_IRQ_VIC1(15) /* S5P6450 */ #define IRQ_SPI0 S5P_IRQ_VIC1(16) #define IRQ_SPI1 S5P_IRQ_VIC1(17) +#define IRQ_HSMMC2 S5P_IRQ_VIC1(17) /* Shared */ #define IRQ_IIC S5P_IRQ_VIC1(18) #define IRQ_DISPCON3 S5P_IRQ_VIC1(19) -#define IRQ_FIMGVG S5P_IRQ_VIC1(20) #define IRQ_EINT_GROUPS S5P_IRQ_VIC1(21) -#define IRQ_PMU S5P_IRQ_VIC1(23) +#define IRQ_PMU S5P_IRQ_VIC1(23) /* S5P6440 */ #define IRQ_HSMMC0 S5P_IRQ_VIC1(24) #define IRQ_HSMMC1 S5P_IRQ_VIC1(25) -#define IRQ_HSMMC2 IRQ_SPI1 /* shared with SPI1 */ #define IRQ_OTG S5P_IRQ_VIC1(26) #define IRQ_DSI S5P_IRQ_VIC1(27) #define IRQ_RTC_ALARM S5P_IRQ_VIC1(28) @@ -63,6 +69,24 @@ #define IRQ_TC IRQ_PENDN #define IRQ_ADC S5P_IRQ_VIC1(31) +/* UART interrupts, S5P6450 has 5 UARTs */ +#define IRQ_S5P_UART_BASE4 (96) +#define IRQ_S5P_UART_BASE5 (100) + +#define IRQ_S5P_UART_RX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_RXD) +#define IRQ_S5P_UART_TX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_TXD) +#define IRQ_S5P_UART_ERR4 (IRQ_S5P_UART_BASE4 + UART_IRQ_ERR) + +#define IRQ_S5P_UART_RX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_RXD) +#define IRQ_S5P_UART_TX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_TXD) +#define IRQ_S5P_UART_ERR5 (IRQ_S5P_UART_BASE5 + UART_IRQ_ERR) + +/* S3C compatibilty defines */ +#define IRQ_S3CUART_RX4 IRQ_S5P_UART_RX4 +#define IRQ_S3CUART_RX5 IRQ_S5P_UART_RX5 + +/* S5P6450 EINT feature will be added */ + /* * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place @@ -115,4 +139,4 @@ #define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1) -#endif /* __ASM_ARCH_S5P_IRQS_H */ +#endif /* __ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h new file mode 100644 index 0000000..31e5341 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/map.h @@ -0,0 +1,83 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/map.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Memory map definitions + * + * 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. +*/ + +#ifndef __ASM_ARCH_MAP_H +#define __ASM_ARCH_MAP_H __FILE__ + +#include <plat/map-base.h> +#include <plat/map-s5p.h> + +#define S5P64X0_PA_SDRAM (0x20000000) + +#define S5P64X0_PA_CHIPID (0xE0000000) +#define S5P_PA_CHIPID S5P64X0_PA_CHIPID + +#define S5P64X0_PA_SYSCON (0xE0100000) +#define S5P_PA_SYSCON S5P64X0_PA_SYSCON + +#define S5P64X0_PA_GPIO (0xE0308000) + +#define S5P64X0_PA_VIC0 (0xE4000000) +#define S5P64X0_PA_VIC1 (0xE4100000) + +#define S5P64X0_PA_PDMA (0xE9000000) + +#define S5P64X0_PA_TIMER (0xEA000000) +#define S5P_PA_TIMER S5P64X0_PA_TIMER + +#define S5P64X0_PA_RTC (0xEA100000) + +#define S5P64X0_PA_WDT (0xEA200000) + +#define S5P6440_PA_UART(x) (0xEC000000 + ((x) * S3C_UART_OFFSET)) +#define S5P6450_PA_UART(x) ((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000)) + +#define S5P_PA_UART0 S5P6450_PA_UART(0) +#define S5P_PA_UART1 S5P6450_PA_UART(1) +#define S5P_PA_UART2 S5P6450_PA_UART(2) +#define S5P_PA_UART3 S5P6450_PA_UART(3) +#define S5P_PA_UART4 S5P6450_PA_UART(4) +#define S5P_PA_UART5 S5P6450_PA_UART(5) + +#define S5P_SZ_UART SZ_256 + +#define S5P6440_PA_IIC0 (0xEC104000) +#define S5P6440_PA_IIC1 (0xEC20F000) +#define S5P6450_PA_IIC0 (0xEC100000) +#define S5P6450_PA_IIC1 (0xEC200000) + +#define S5P64X0_PA_SPI0 (0xEC400000) +#define S5P64X0_PA_SPI1 (0xEC500000) + +#define S5P64X0_PA_HSOTG (0xED100000) + +#define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000)) + +#define S5P64X0_PA_I2S (0xF2000000) + +#define S5P64X0_PA_PCM (0xF2100000) + +#define S5P64X0_PA_ADC (0xF3000000) + +/* compatibiltiy defines. */ + +#define S3C_PA_HSMMC0 S5P64X0_PA_HSMMC(0) +#define S3C_PA_HSMMC1 S5P64X0_PA_HSMMC(1) +#define S3C_PA_HSMMC2 S5P64X0_PA_HSMMC(2) +#define S3C_PA_IIC S5P6440_PA_IIC0 +#define S3C_PA_IIC1 S5P6440_PA_IIC1 +#define S3C_PA_RTC S5P64X0_PA_RTC +#define S3C_PA_WDT S5P64X0_PA_WDT + +#define SAMSUNG_PA_ADC S5P64X0_PA_ADC + +#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h index d62910c..1b036b0 100644 --- a/arch/arm/mach-s5p6440/include/mach/memory.h +++ b/arch/arm/mach-s5p64x0/include/mach/memory.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/memory.h +/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - Memory definitions + * S5P64X0 - Memory definitions * * 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 @@ -11,9 +11,9 @@ */ #ifndef __ASM_ARCH_MEMORY_H -#define __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x20000000) +#define PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE SZ_8M #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h index 6a2a02f..19fff8b 100644 --- a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h +++ b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h @@ -1,16 +1,14 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h +/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * http://armlinux.simtec.co.uk/ * - * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h - * - * S5P6440 - pwm clock and timer support + * S5P64X0 - pwm clock and timer support * * 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/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h new file mode 100644 index 0000000..58e1bc8 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h @@ -0,0 +1,63 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/regs-clock.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Clock register definitions + * + * 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. +*/ + +#ifndef __ASM_ARCH_REGS_CLOCK_H +#define __ASM_ARCH_REGS_CLOCK_H __FILE__ + +#include <mach/map.h> + +#define S5P_CLKREG(x) (S3C_VA_SYS + (x)) + +#define S5P64X0_APLL_CON S5P_CLKREG(0x0C) +#define S5P64X0_MPLL_CON S5P_CLKREG(0x10) +#define S5P64X0_EPLL_CON S5P_CLKREG(0x14) +#define S5P64X0_EPLL_CON_K S5P_CLKREG(0x18) + +#define S5P64X0_CLK_SRC0 S5P_CLKREG(0x1C) + +#define S5P64X0_CLK_DIV0 S5P_CLKREG(0x20) +#define S5P64X0_CLK_DIV1 S5P_CLKREG(0x24) +#define S5P64X0_CLK_DIV2 S5P_CLKREG(0x28) + +#define S5P64X0_CLK_GATE_HCLK0 S5P_CLKREG(0x30) +#define S5P64X0_CLK_GATE_PCLK S5P_CLKREG(0x34) +#define S5P64X0_CLK_GATE_SCLK0 S5P_CLKREG(0x38) +#define S5P64X0_CLK_GATE_MEM0 S5P_CLKREG(0x3C) + +#define S5P64X0_CLK_DIV3 S5P_CLKREG(0x40) + +#define S5P64X0_CLK_GATE_HCLK1 S5P_CLKREG(0x44) +#define S5P64X0_CLK_GATE_SCLK1 S5P_CLKREG(0x48) + +#define S5P6450_DPLL_CON S5P_CLKREG(0x50) +#define S5P6450_DPLL_CON_K S5P_CLKREG(0x54) + +#define S5P64X0_CLK_SRC1 S5P_CLKREG(0x10C) + +#define S5P64X0_SYS_ID S5P_CLKREG(0x118) +#define S5P64X0_SYS_OTHERS S5P_CLKREG(0x11C) + +#define S5P64X0_PWR_CFG S5P_CLKREG(0x804) +#define S5P64X0_OTHERS S5P_CLKREG(0x900) + +#define S5P64X0_CLKDIV0_HCLK_SHIFT (8) +#define S5P64X0_CLKDIV0_HCLK_MASK (0xF << S5P64X0_CLKDIV0_HCLK_SHIFT) + +#define S5P64X0_OTHERS_USB_SIG_MASK (1 << 16) + +/* Compatibility defines */ + +#define ARM_CLK_DIV S5P64X0_CLK_DIV0 +#define ARM_DIV_RATIO_SHIFT 0 +#define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT) + +#endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h index 82ff753..85f448e 100644 --- a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h @@ -1,21 +1,24 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h +/* linux/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - GPIO register definitions + * S5P64X0 - GPIO register definitions * * 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. - */ +*/ #ifndef __ASM_ARCH_REGS_GPIO_H #define __ASM_ARCH_REGS_GPIO_H __FILE__ #include <mach/map.h> +/* Will be implemented S5P6442 GPIOlib */ + /* Base addresses for each of the banks */ + #define S5P6440_GPA_BASE (S5P_VA_GPIO + 0x0000) #define S5P6440_GPB_BASE (S5P_VA_GPIO + 0x0020) #define S5P6440_GPC_BASE (S5P_VA_GPIO + 0x0040) @@ -27,6 +30,7 @@ #define S5P6440_GPN_BASE (S5P_VA_GPIO + 0x0830) #define S5P6440_GPP_BASE (S5P_VA_GPIO + 0x0160) #define S5P6440_GPR_BASE (S5P_VA_GPIO + 0x0290) + #define S5P6440_EINT0CON0 (S5P_VA_GPIO + 0x900) #define S5P6440_EINT0FLTCON0 (S5P_VA_GPIO + 0x910) #define S5P6440_EINT0FLTCON1 (S5P_VA_GPIO + 0x914) @@ -34,19 +38,23 @@ #define S5P6440_EINT0PEND (S5P_VA_GPIO + 0x924) /* for LCD */ + #define S5P6440_SPCON_LCD_SEL_RGB (1 << 0) #define S5P6440_SPCON_LCD_SEL_MASK (3 << 0) -/* These set of macros are not really useful for the - * GPF/GPI/GPJ/GPN/GPP, - * useful for others set of GPIO's (4 bit) +/* + * These set of macros are not really useful for the + * GPF/GPI/GPJ/GPN/GPP, useful for others set of GPIO's (4 bit) */ + #define S5P6440_GPIO_CONMASK(__gpio) (0xf << ((__gpio) * 4)) #define S5P6440_GPIO_INPUT(__gpio) (0x0 << ((__gpio) * 4)) #define S5P6440_GPIO_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) -/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit) - * */ +/* + * Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit) + */ + #define S5P6440_GPIO2_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) #define S5P6440_GPIO2_INPUT(__gpio) (0x0 << ((__gpio) * 2)) #define S5P6440_GPIO2_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) diff --git a/arch/arm/mach-s5p6440/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h index a961f4b..4aaebda 100644 --- a/arch/arm/mach-s5p6440/include/mach/regs-irq.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/regs-irq.h +/* linux/arch/arm/mach-s5p64x0/include/mach/regs-irq.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - IRQ register definitions + * S5P64X0 - IRQ register definitions * * 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/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h new file mode 100644 index 0000000..ff85b4b --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h @@ -0,0 +1,46 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Header file for s5p64x0 clock support + * + * 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. +*/ + +#ifndef __ASM_ARCH_CLOCK_H +#define __ASM_ARCH_CLOCK_H __FILE__ + +#include <linux/clk.h> + +extern struct clksrc_clk clk_mout_apll; +extern struct clksrc_clk clk_mout_mpll; +extern struct clksrc_clk clk_mout_epll; + +extern int s5p64x0_epll_enable(struct clk *clk, int enable); +extern unsigned long s5p64x0_epll_get_rate(struct clk *clk); + +extern unsigned long s5p64x0_armclk_get_rate(struct clk *clk); +extern unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate); +extern int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate); + +extern struct clk_ops s5p64x0_clkarm_ops; + +extern struct clksrc_clk clk_armclk; +extern struct clksrc_clk clk_dout_mpll; + +extern struct clk *clkset_hclk_low_list[]; +extern struct clksrc_sources clkset_hclk_low; + +extern int s5p64x0_pclk_ctrl(struct clk *clk, int enable); +extern int s5p64x0_hclk0_ctrl(struct clk *clk, int enable); +extern int s5p64x0_hclk1_ctrl(struct clk *clk, int enable); +extern int s5p64x0_sclk_ctrl(struct clk *clk, int enable); +extern int s5p64x0_sclk1_ctrl(struct clk *clk, int enable); +extern int s5p64x0_mem_ctrl(struct clk *clk, int enable); + +extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable); + +#endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h new file mode 100644 index 0000000..170a20a --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h @@ -0,0 +1,20 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh <jassi.brar@samsung.com> + * + * 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. +*/ + +#ifndef __ASM_ARCH_SPI_CLKS_H +#define __ASM_ARCH_SPI_CLKS_H __FILE__ + +#define S5P64X0_SPI_SRCCLK_PCLK 0 +#define S5P64X0_SPI_SRCCLK_SCLK 1 + +#endif /* __ASM_ARCH_SPI_CLKS_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/system.h b/arch/arm/mach-s5p64x0/include/mach/system.h index a359ee3..60f5753 100644 --- a/arch/arm/mach-s5p6440/include/mach/system.h +++ b/arch/arm/mach-s5p64x0/include/mach/system.h @@ -1,9 +1,9 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/system.h +/* linux/arch/arm/mach-s5p64x0/include/mach/system.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - system support header + * S5P64X0 - system support header * * 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/arch/arm/mach-s5p6440/include/mach/tick.h b/arch/arm/mach-s5p64x0/include/mach/tick.h index 2f25c7f..00aa7f1 100644 --- a/arch/arm/mach-s5p6440/include/mach/tick.h +++ b/arch/arm/mach-s5p64x0/include/mach/tick.h @@ -1,9 +1,14 @@ -/* linux/arch/arm/mach-s5p6440/include/mach/tick.h +/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * - * S5P6440 - Timer tick support definitions + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S5P64X0 - Timer tick support definitions * * 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/arch/arm/mach-s5p6440/include/mach/timex.h b/arch/arm/mach-s5p64x0/include/mach/timex.h index fb2e8cd..4b91faa 100644 --- a/arch/arm/mach-s5p6440/include/mach/timex.h +++ b/arch/arm/mach-s5p64x0/include/mach/timex.h @@ -1,9 +1,12 @@ -/* arch/arm/mach-s3c64xx/include/mach/timex.h +/* linux/arch/arm/mach-s5p64x0/include/mach/timex.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Copyright (c) 2003-2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * - * S3C6400 - time parameters + * S5P64X0 - time parameters * * 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/arch/arm/mach-s5p64x0/include/mach/uncompress.h b/arch/arm/mach-s5p64x0/include/mach/uncompress.h new file mode 100644 index 0000000..c65b229 --- /dev/null +++ b/arch/arm/mach-s5p64x0/include/mach/uncompress.h @@ -0,0 +1,212 @@ +/* linux/arch/arm/mach-s5p64x0/include/mach/uncompress.h + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - uncompress code + * + * 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. +*/ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include <mach/map.h> + +/* + * cannot use commonly <plat/uncompress.h> + * because uart base of S5P6440 and S5P6450 is different + */ + +typedef unsigned int upf_t; /* cannot include linux/serial_core.h */ + +/* uart setup */ + +static unsigned int fifo_mask; +static unsigned int fifo_max; + +/* forward declerations */ + +static void arch_detect_cpu(void); + +/* defines for UART registers */ + +#include <plat/regs-serial.h> +#include <plat/regs-watchdog.h> + +/* working in physical space... */ +#undef S3C2410_WDOGREG +#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x))) + +/* how many bytes we allow into the FIFO at a time in FIFO mode */ +#define FIFO_MAX (14) + +static unsigned long uart_base; + +static __inline__ void get_uart_base(void) +{ + unsigned int chipid; + + chipid = *(const volatile unsigned int __force *) 0xE0100118; + + uart_base = S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT; + + if ((chipid & 0xff000) == 0x50000) + uart_base += 0xEC800000; + else + uart_base += 0xEC000000; +} + +static __inline__ void uart_wr(unsigned int reg, unsigned int val) +{ + volatile unsigned int *ptr; + + get_uart_base(); + ptr = (volatile unsigned int *)(reg + uart_base); + *ptr = val; +} + +static __inline__ unsigned int uart_rd(unsigned int reg) +{ + volatile unsigned int *ptr; + + get_uart_base(); + ptr = (volatile unsigned int *)(reg + uart_base); + return *ptr; +} + +/* + * we can deal with the case the UARTs are being run + * in FIFO mode, so that we don't hold up our execution + * waiting for tx to happen... + */ + +static void putc(int ch) +{ + if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) { + int level; + + while (1) { + level = uart_rd(S3C2410_UFSTAT); + level &= fifo_mask; + + if (level < fifo_max) + break; + } + + } else { + /* not using fifos */ + + while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE) + barrier(); + } + + /* write byte to transmission register */ + uart_wr(S3C2410_UTXH, ch); +} + +static inline void flush(void) +{ +} + +#define __raw_writel(d, ad) \ + do { \ + *((volatile unsigned int __force *)(ad)) = (d); \ + } while (0) + +/* + * CONFIG_S3C_BOOT_WATCHDOG + * + * Simple boot-time watchdog setup, to reboot the system if there is + * any problem with the boot process + */ + +#ifdef CONFIG_S3C_BOOT_WATCHDOG + +#define WDOG_COUNT (0xff00) + +static inline void arch_decomp_wdog(void) +{ + __raw_writel(WDOG_COUNT, S3C2410_WTCNT); +} + +static void arch_decomp_wdog_start(void) +{ + __raw_writel(WDOG_COUNT, S3C2410_WTDAT); + __raw_writel(WDOG_COUNT, S3C2410_WTCNT); + __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON); +} + +#else +#define arch_decomp_wdog_start() +#define arch_decomp_wdog() +#endif + +#ifdef CONFIG_S3C_BOOT_ERROR_RESET + +static void arch_decomp_error(const char *x) +{ + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System resetting\n"); + + __raw_writel(0x4000, S3C2410_WTDAT); + __raw_writel(0x4000, S3C2410_WTCNT); + __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON); + + while(1); +} + +#define arch_error arch_decomp_error +#endif + +#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO +static inline void arch_enable_uart_fifo(void) +{ + u32 fifocon = uart_rd(S3C2410_UFCON); + + if (!(fifocon & S3C2410_UFCON_FIFOMODE)) { + fifocon |= S3C2410_UFCON_RESETBOTH; + uart_wr(S3C2410_UFCON, fifocon); + + /* wait for fifo reset to complete */ + while (1) { + fifocon = uart_rd(S3C2410_UFCON); + if (!(fifocon & S3C2410_UFCON_RESETBOTH)) + break; + } + } +} +#else +#define arch_enable_uart_fifo() do { } while(0) +#endif + +static void arch_decomp_setup(void) +{ + /* + * we may need to setup the uart(s) here if we are not running + * on an BAST... the BAST will have left the uarts configured + * after calling linux. + */ + + arch_detect_cpu(); + arch_decomp_wdog_start(); + + /* + * Enable the UART FIFOs if they where not enabled and our + * configuration says we should turn them on. + */ + + arch_enable_uart_fifo(); +} + + + +static void arch_detect_cpu(void) +{ + /* we do not need to do any cpu detection here at the moment. */ +} + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/vmalloc.h b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h index e3f0eeb..97a9df3 100644 --- a/arch/arm/mach-s5p6440/include/mach/vmalloc.h +++ b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h @@ -1,4 +1,7 @@ -/* arch/arm/mach-s5p6440/include/mach/vmalloc.h +/* linux/arch/arm/mach-s5p64x0/include/mach/vmalloc.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Copyright 2010 Ben Dooks <ben-linux@fluff.org> * diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c new file mode 100644 index 0000000..79833ca --- /dev/null +++ b/arch/arm/mach-s5p64x0/init.c @@ -0,0 +1,73 @@ +/* linux/arch/arm/mach-s5p64x0/init.c + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * S5P64X0 - Init support + * + * 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/kernel.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/serial_core.h> + +#include <mach/map.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/s5p6440.h> +#include <plat/s5p6450.h> +#include <plat/regs-serial.h> + +static struct s3c24xx_uart_clksrc s5p64x0_serial_clocks[] = { + [0] = { + .name = "pclk_low", + .divisor = 1, + .min_baud = 0, + .max_baud = 0, + }, + [1] = { + .name = "uclk1", + .divisor = 1, + .min_baud = 0, + .max_baud = 0, + }, +}; + +/* uart registration process */ + +void __init s5p64x0_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + struct s3c2410_uartcfg *tcfg = cfg; + u32 ucnt; + + for (ucnt = 0; ucnt < no; ucnt++, tcfg++) { + if (!tcfg->clocks) { + tcfg->clocks = s5p64x0_serial_clocks; + tcfg->clocks_size = ARRAY_SIZE(s5p64x0_serial_clocks); + } + } +} + +void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + int uart; + + for (uart = 0; uart < no; uart++) { + s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart); + s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART; + } + + s5p64x0_common_init_uarts(cfg, no); + s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); +} + +void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s5p64x0_common_init_uarts(cfg, no); + s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); +} diff --git a/arch/arm/mach-s5p6440/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index 9202aaa..28de0a5 100644 --- a/arch/arm/mach-s5p6440/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -1,7 +1,7 @@ -/* linux/arch/arm/mach-s5p6440/mach-smdk6440.c +/* linux/arch/arm/mach-s5p64x0/mach-smdk6440.c * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * 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 @@ -21,21 +21,22 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/clk.h> +#include <linux/gpio.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <asm/irq.h> +#include <asm/mach-types.h> #include <mach/hardware.h> #include <mach/map.h> - -#include <asm/irq.h> -#include <asm/mach-types.h> +#include <mach/regs-clock.h> +#include <mach/i2c.h> #include <plat/regs-serial.h> - +#include <plat/gpio-cfg.h> #include <plat/s5p6440.h> #include <plat/clock.h> -#include <mach/regs-clock.h> #include <plat/devs.h> #include <plat/cpu.h> #include <plat/iic.h> @@ -58,43 +59,60 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { [0] = { - .hwport = 0, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 0, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [1] = { - .hwport = 1, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 1, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [2] = { - .hwport = 2, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 2, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, [3] = { - .hwport = 3, - .flags = 0, - .ucon = SMDK6440_UCON_DEFAULT, - .ulcon = SMDK6440_ULCON_DEFAULT, - .ufcon = SMDK6440_UFCON_DEFAULT, + .hwport = 3, + .flags = 0, + .ucon = SMDK6440_UCON_DEFAULT, + .ulcon = SMDK6440_ULCON_DEFAULT, + .ufcon = SMDK6440_UFCON_DEFAULT, }, }; static struct platform_device *smdk6440_devices[] __initdata = { - &s5p6440_device_iis, &s3c_device_adc, &s3c_device_rtc, &s3c_device_i2c0, &s3c_device_i2c1, &s3c_device_ts, &s3c_device_wdt, + &s5p6440_device_iis, +}; + +static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = { + .flags = 0, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6440_i2c0_cfg_gpio, +}; + +static struct s3c2410_platform_i2c s5p6440_i2c1_data __initdata = { + .flags = 0, + .bus_num = 1, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6440_i2c1_cfg_gpio, }; static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = { @@ -113,7 +131,7 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { static void __init smdk6440_map_io(void) { - s5p_init_io(NULL, 0, S5P_SYS_ID); + s5p_init_io(NULL, 0, S5P64X0_SYS_ID); s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs)); } @@ -122,9 +140,8 @@ static void __init smdk6440_machine_init(void) { s3c24xx_ts_set_platdata(&s3c_ts_platform); - /* I2C */ - s3c_i2c0_set_platdata(NULL); - s3c_i2c1_set_platdata(NULL); + s3c_i2c0_set_platdata(&s5p6440_i2c0_data); + s3c_i2c1_set_platdata(&s5p6440_i2c1_data); i2c_register_board_info(0, smdk6440_i2c_devs0, ARRAY_SIZE(smdk6440_i2c_devs0)); i2c_register_board_info(1, smdk6440_i2c_devs1, @@ -135,9 +152,9 @@ static void __init smdk6440_machine_init(void) MACHINE_START(SMDK6440, "SMDK6440") /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ - .phys_io = S3C_PA_UART & 0xfff00000, + .phys_io = S5P6440_PA_UART(0) & 0xfff00000, .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, - .boot_params = S5P_PA_SDRAM + 0x100, + .boot_params = S5P64X0_PA_SDRAM + 0x100, .init_irq = s5p6440_init_irq, .map_io = smdk6440_map_io, diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c new file mode 100644 index 0000000..8e98217 --- /dev/null +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -0,0 +1,182 @@ +/* linux/arch/arm/mach-s5p64x0/mach-smdk6450.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * 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/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/gpio.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/i2c.h> + +#include <plat/regs-serial.h> +#include <plat/gpio-cfg.h> +#include <plat/s5p6450.h> +#include <plat/clock.h> +#include <plat/devs.h> +#include <plat/cpu.h> +#include <plat/iic.h> +#include <plat/pll.h> +#include <plat/adc.h> +#include <plat/ts.h> + +#define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) + +#define SMDK6450_ULCON_DEFAULT S3C2410_LCON_CS8 + +#define SMDK6450_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S3C2440_UFCON_TXTRIG16 | \ + S3C2410_UFCON_RXTRIG8) + +static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, +#if CONFIG_SERIAL_SAMSUNG_UARTS > 4 + [4] = { + .hwport = 4, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, +#endif +#if CONFIG_SERIAL_SAMSUNG_UARTS > 5 + [5] = { + .hwport = 5, + .flags = 0, + .ucon = SMDK6450_UCON_DEFAULT, + .ulcon = SMDK6450_ULCON_DEFAULT, + .ufcon = SMDK6450_UFCON_DEFAULT, + }, +#endif +}; + +static struct platform_device *smdk6450_devices[] __initdata = { + &s3c_device_adc, + &s3c_device_rtc, + &s3c_device_i2c0, + &s3c_device_i2c1, + &s3c_device_ts, + &s3c_device_wdt, + &s5p6450_device_iis0, + /* s5p6450_device_spi0 will be added */ +}; + +static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = { + .flags = 0, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6450_i2c0_cfg_gpio, +}; + +static struct s3c2410_platform_i2c s5p6450_i2c1_data __initdata = { + .flags = 0, + .bus_num = 1, + .slave_addr = 0x10, + .frequency = 100*1000, + .sda_delay = 100, + .cfg_gpio = s5p6450_i2c1_cfg_gpio, +}; + +static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = { + { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung KS24C080C EEPROM */ +}; + +static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = { + { I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */ +}; + +static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { + .delay = 10000, + .presc = 49, + .oversampling_shift = 2, +}; + +static void __init smdk6450_map_io(void) +{ + s5p_init_io(NULL, 0, S5P64X0_SYS_ID); + s3c24xx_init_clocks(19200000); + s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs)); +} + +static void __init smdk6450_machine_init(void) +{ + s3c24xx_ts_set_platdata(&s3c_ts_platform); + + s3c_i2c0_set_platdata(&s5p6450_i2c0_data); + s3c_i2c1_set_platdata(&s5p6450_i2c1_data); + i2c_register_board_info(0, smdk6450_i2c_devs0, + ARRAY_SIZE(smdk6450_i2c_devs0)); + i2c_register_board_info(1, smdk6450_i2c_devs1, + ARRAY_SIZE(smdk6450_i2c_devs1)); + + platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices)); +} + +MACHINE_START(SMDK6450, "SMDK6450") + /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ + .phys_io = S5P6450_PA_UART(0) & 0xfff00000, + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, + .boot_params = S5P64X0_PA_SDRAM + 0x100, + + .init_irq = s5p6450_init_irq, + .map_io = smdk6450_map_io, + .init_machine = smdk6450_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-s5p6440/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c index 2c99d14..dc4cc65 100644 --- a/arch/arm/mach-s5p6440/setup-i2c0.c +++ b/arch/arm/mach-s5p64x0/setup-i2c0.c @@ -1,11 +1,11 @@ -/* linux/arch/arm/mach-s5p6440/setup-i2c0.c +/* linux/arch/arm/mach-s5p64x0/setup-i2c0.c * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * I2C0 GPIO configuration. * - * Based on plat-s3c64xx/setup-i2c0.c + * Based on plat-s3c64x0/setup-i2c0.c * * 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 @@ -14,17 +14,29 @@ #include <linux/kernel.h> #include <linux/types.h> +#include <linux/gpio.h> struct platform_device; /* don't need the contents */ -#include <linux/gpio.h> #include <plat/gpio-cfg.h> #include <plat/iic.h> -void s3c_i2c0_cfg_gpio(struct platform_device *dev) +#include <mach/i2c.h> + +void s5p6440_i2c0_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2)); s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2)); s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP); } + +void s5p6450_i2c0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S5P6450_GPB(5), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5P6450_GPB(5), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6450_GPB(6), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5P6450_GPB(6), S3C_GPIO_PULL_UP); +} + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) { } diff --git a/arch/arm/mach-s5p6440/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c index 9a1537f..2edd791 100644 --- a/arch/arm/mach-s5p6440/setup-i2c1.c +++ b/arch/arm/mach-s5p64x0/setup-i2c1.c @@ -1,7 +1,7 @@ -/* linux/arch/arm/mach-s5p6440/setup-i2c1.c +/* linux/arch/arm/mach-s5p64xx/setup-i2c1.c * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * I2C1 GPIO configuration. * @@ -21,10 +21,22 @@ struct platform_device; /* don't need the contents */ #include <plat/gpio-cfg.h> #include <plat/iic.h> -void s3c_i2c1_cfg_gpio(struct platform_device *dev) +#include <mach/i2c.h> + +void s5p6440_i2c1_cfg_gpio(struct platform_device *dev) { s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6)); s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6)); s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP); } + +void s5p6450_i2c1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S5P6450_GPR(9), S3C_GPIO_SFN(6)); + s3c_gpio_setpull(S5P6450_GPR(9), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6450_GPR(10), S3C_GPIO_SFN(6)); + s3c_gpio_setpull(S5P6450_GPR(10), S3C_GPIO_PULL_UP); +} + +void s3c_i2c1_cfg_gpio(struct platform_device *dev) { } diff --git a/arch/arm/mach-s5pc100/cpu.c b/arch/arm/mach-s5pc100/cpu.c index 251c92a..fd2708e 100644 --- a/arch/arm/mach-s5pc100/cpu.c +++ b/arch/arm/mach-s5pc100/cpu.c @@ -1,5 +1,8 @@ /* linux/arch/arm/mach-s5pc100/cpu.c * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * * Copyright 2009 Samsung Electronics Co. * Byungho Min <bhmin@samsung.com> * @@ -21,6 +24,7 @@ #include <linux/sysdev.h> #include <linux/serial_core.h> #include <linux/platform_device.h> +#include <linux/sched.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -56,11 +60,31 @@ static struct map_desc s5pc100_iodesc[] __initdata = { .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5PC100_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5PC100_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5PC100_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)VA_VIC2, - .pfn = __phys_to_pfn(S5P_PA_VIC2), + .pfn = __phys_to_pfn(S5PC100_PA_VIC2), .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)S5PC100_VA_OTHERS, .pfn = __phys_to_pfn(S5PC100_PA_OTHERS), .length = SZ_4K, diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h index 01b9134..8751ef4 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -44,19 +44,16 @@ #define S5PC100_PA_OTHERS (0xE0200000) #define S5PC100_VA_OTHERS (S3C_VA_SYS + 0x10000) -#define S5P_PA_GPIO (0xE0300000) +#define S5PC100_PA_GPIO (0xE0300000) #define S5PC1XX_VA_GPIO S3C_ADDR(0x00500000) /* Interrupt */ -#define S5PC100_PA_VIC (0xE4000000) +#define S5PC100_PA_VIC0 (0xE4000000) +#define S5PC100_PA_VIC1 (0xE4100000) +#define S5PC100_PA_VIC2 (0xE4200000) #define S5PC100_VA_VIC S3C_VA_IRQ -#define S5PC100_PA_VIC_OFFSET 0x100000 #define S5PC100_VA_VIC_OFFSET 0x10000 -#define S5PC1XX_PA_VIC(x) (S5PC100_PA_VIC + ((x) * S5PC100_PA_VIC_OFFSET)) #define S5PC1XX_VA_VIC(x) (S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET)) -#define S5P_PA_VIC0 S5PC1XX_PA_VIC(0) -#define S5P_PA_VIC1 S5PC1XX_PA_VIC(1) -#define S5P_PA_VIC2 S5PC1XX_PA_VIC(2) #define S5PC100_PA_ONENAND (0xE7100000) diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig index d3a3895..5315fec 100644 --- a/arch/arm/mach-s5pv210/Kconfig +++ b/arch/arm/mach-s5pv210/Kconfig @@ -53,11 +53,6 @@ config S5PV210_SETUP_SDHCI_GPIO help Common setup code for SDHCI gpio. -config S5PC110_DEV_ONENAND - bool - help - Compile in platform device definition for OneNAND1 controller - menu "S5PC110 Machines" config MACH_AQUILA @@ -71,7 +66,7 @@ config MACH_AQUILA select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 - select S5PC110_DEV_ONENAND + select S5P_DEV_ONENAND select S5PV210_SETUP_FB_24BPP select S5PV210_SETUP_SDHCI help @@ -88,7 +83,7 @@ config MACH_GONI select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 - select S5PC110_DEV_ONENAND + select S5P_DEV_ONENAND select S5PV210_SETUP_FB_24BPP select S5PV210_SETUP_SDHCI help diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 05048c5..7045489 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_MACH_GONI) += mach-goni.o obj-y += dev-audio.o obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o -obj-$(CONFIG_S5PC110_DEV_ONENAND) += dev-onenand.o obj-$(CONFIG_S5PV210_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index af91fef..d562670 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -173,11 +173,6 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); } -static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable) -{ - return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable); -} - static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable); @@ -281,6 +276,24 @@ static struct clk init_clocks_disable[] = { .enable = s5pv210_clk_ip0_ctrl, .ctrlbit = (1<<29), }, { + .name = "fimc", + .id = 0, + .parent = &clk_hclk_dsys.clk, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 24), + }, { + .name = "fimc", + .id = 1, + .parent = &clk_hclk_dsys.clk, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "fimc", + .id = 2, + .parent = &clk_hclk_dsys.clk, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 26), + }, { .name = "otg", .id = -1, .parent = &clk_hclk_psys.clk, @@ -357,7 +370,7 @@ static struct clk init_clocks_disable[] = { .id = 1, .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, - .ctrlbit = (1<<8), + .ctrlbit = (1 << 10), }, { .name = "i2c", .id = 2, diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c index b9f4d67..2f16bfc 100644 --- a/arch/arm/mach-s5pv210/cpu.c +++ b/arch/arm/mach-s5pv210/cpu.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-s5pv210/cpu.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * http://www.samsung.com * * 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 @@ -19,6 +19,7 @@ #include <linux/io.h> #include <linux/sysdev.h> #include <linux/platform_device.h> +#include <linux/sched.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -47,7 +48,22 @@ static struct map_desc s5pv210_iodesc[] __initdata = { { .virtual = (unsigned long)S5P_VA_SYSTIMER, .pfn = __phys_to_pfn(S5PV210_PA_SYSTIMER), - .length = SZ_1M, + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5PV210_PA_GPIO), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC0, + .pfn = __phys_to_pfn(S5PV210_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)VA_VIC1, + .pfn = __phys_to_pfn(S5PV210_PA_VIC1), + .length = SZ_16K, .type = MT_DEVICE, }, { .virtual = (unsigned long)VA_VIC2, @@ -60,6 +76,11 @@ static struct map_desc s5pv210_iodesc[] __initdata = { .length = SZ_16K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)S5P_VA_SROMC, .pfn = __phys_to_pfn(S5PV210_PA_SROMC), .length = SZ_4K, diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index dd4fb6b..bd9afd5 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -17,7 +17,10 @@ #include <plat/map-s5p.h> #define S5PC110_PA_ONENAND (0xB0000000) +#define S5P_PA_ONENAND S5PC110_PA_ONENAND + #define S5PC110_PA_ONENAND_DMA (0xB0600000) +#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA #define S5PV210_PA_CHIPID (0xE0000000) #define S5P_PA_CHIPID S5PV210_PA_CHIPID @@ -26,7 +29,6 @@ #define S5P_PA_SYSCON S5PV210_PA_SYSCON #define S5PV210_PA_GPIO (0xE0200000) -#define S5P_PA_GPIO S5PV210_PA_GPIO /* SPI */ #define S5PV210_PA_SPI0 0xE1300000 @@ -72,16 +74,9 @@ #define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000)) #define S5PV210_PA_VIC0 (0xF2000000) -#define S5P_PA_VIC0 S5PV210_PA_VIC0 - #define S5PV210_PA_VIC1 (0xF2100000) -#define S5P_PA_VIC1 S5PV210_PA_VIC1 - #define S5PV210_PA_VIC2 (0xF2200000) -#define S5P_PA_VIC2 S5PV210_PA_VIC2 - #define S5PV210_PA_VIC3 (0xF2300000) -#define S5P_PA_VIC3 S5PV210_PA_VIC3 #define S5PV210_PA_SDRAM (0x20000000) #define S5P_PA_SDRAM S5PV210_PA_SDRAM diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 0dda801..bf772de 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -477,7 +477,7 @@ static struct platform_device *aquila_devices[] __initdata = { &aquila_i2c_gpio_pmic, &aquila_device_gpiokeys, &s3c_device_fb, - &s5pc110_device_onenand, + &s5p_device_onenand, &s3c_device_hsmmc0, &s3c_device_hsmmc1, &s3c_device_hsmmc2, diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 53754d7..fdc5cca 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -456,7 +456,7 @@ static void goni_setup_sdhci(void) static struct platform_device *goni_devices[] __initdata = { &s3c_device_fb, - &s5pc110_device_onenand, + &s5p_device_onenand, &goni_i2c_gpio_pmic, &goni_device_gpiokeys, &s5p_device_fimc0, diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c index e5b261a..4add398 100644 --- a/arch/arm/mach-s5pv310/cpu.c +++ b/arch/arm/mach-s5pv310/cpu.c @@ -31,9 +31,14 @@ extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq); /* Initial IO mappings */ static struct map_desc s5pv310_iodesc[] __initdata = { { - .virtual = (unsigned long)S5P_VA_COREPERI_BASE, - .pfn = __phys_to_pfn(S5PV310_PA_COREPERI), - .length = SZ_8K, + .virtual = (unsigned long)S5P_VA_SYSRAM, + .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5P_VA_CMU, + .pfn = __phys_to_pfn(S5PV310_PA_CMU), + .length = SZ_128K, .type = MT_DEVICE, }, { .virtual = (unsigned long)S5P_VA_COMBINER_BASE, @@ -41,19 +46,24 @@ static struct map_desc s5pv310_iodesc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { + .virtual = (unsigned long)S5P_VA_COREPERI_BASE, + .pfn = __phys_to_pfn(S5PV310_PA_COREPERI), + .length = SZ_8K, + .type = MT_DEVICE, + }, { .virtual = (unsigned long)S5P_VA_L2CC, .pfn = __phys_to_pfn(S5PV310_PA_L2CC), .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_SYSRAM, - .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM), + .virtual = (unsigned long)S5P_VA_GPIO, + .pfn = __phys_to_pfn(S5PV310_PA_GPIO1), .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_CMU, - .pfn = __phys_to_pfn(S5PV310_PA_CMU), - .length = SZ_128K, + .virtual = (unsigned long)S3C_VA_UART, + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_512K, .type = MT_DEVICE, }, }; diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h index 4cdedda..471fc3b 100644 --- a/arch/arm/mach-s5pv310/include/mach/irqs.h +++ b/arch/arm/mach-s5pv310/include/mach/irqs.h @@ -68,6 +68,8 @@ #define IRQ_IIC COMBINER_IRQ(27, 0) +#define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0) + /* Set the default NR_IRQS */ #define NR_IRQS COMBINER_IRQ(MAX_COMBINER_NR, 0) diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h index 213e110..aff6d23 100644 --- a/arch/arm/mach-s5pv310/include/mach/map.h +++ b/arch/arm/mach-s5pv310/include/mach/map.h @@ -25,6 +25,12 @@ #define S5PV310_PA_SYSRAM (0x02025000) +#define S5PC210_PA_ONENAND (0x0C000000) +#define S5P_PA_ONENAND S5PC210_PA_ONENAND + +#define S5PC210_PA_ONENAND_DMA (0x0C600000) +#define S5P_PA_ONENAND_DMA S5PC210_PA_ONENAND_DMA + #define S5PV310_PA_CHIPID (0x10000000) #define S5P_PA_CHIPID S5PV310_PA_CHIPID @@ -46,7 +52,6 @@ #define S5PV310_PA_GPIO1 (0x11400000) #define S5PV310_PA_GPIO2 (0x11000000) #define S5PV310_PA_GPIO3 (0x03860000) -#define S5P_PA_GPIO S5PV310_PA_GPIO1 #define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000)) diff --git a/arch/arm/mach-shark/include/mach/vmalloc.h b/arch/arm/mach-shark/include/mach/vmalloc.h index f6c6837..8e845b6 100644 --- a/arch/arm/mach-shark/include/mach/vmalloc.h +++ b/arch/arm/mach-shark/include/mach/vmalloc.h @@ -1,4 +1,4 @@ /* * arch/arm/mach-shark/include/mach/vmalloc.h */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END 0xd0000000 diff --git a/arch/arm/mach-tcc8k/Kconfig b/arch/arm/mach-tcc8k/Kconfig new file mode 100644 index 0000000..ad86415 --- /dev/null +++ b/arch/arm/mach-tcc8k/Kconfig @@ -0,0 +1,11 @@ +if ARCH_TCC8K + +comment "TCC8000 systems:" + +config MACH_TCC8000_SDK + bool "Telechips TCC8000-SDK development kit" + default y + help + Support for the Telechips TCC8000-SDK board. + +endif diff --git a/arch/arm/mach-tcc8k/Makefile b/arch/arm/mach-tcc8k/Makefile new file mode 100644 index 0000000..9bacf31 --- /dev/null +++ b/arch/arm/mach-tcc8k/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for TCC8K boards and common files. +# + +# Common support +obj-y += clock.o irq.o time.o io.o devices.o + +# Board specific support +obj-$(CONFIG_MACH_TCC8000_SDK) += board-tcc8000-sdk.o diff --git a/arch/arm/mach-tcc8k/Makefile.boot b/arch/arm/mach-tcc8k/Makefile.boot new file mode 100644 index 0000000..f135c9d --- /dev/null +++ b/arch/arm/mach-tcc8k/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x20008000 +params_phys-y := 0x20000100 +initrd_phys-y := 0x20800000 diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c new file mode 100644 index 0000000..4e42555 --- /dev/null +++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * 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/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <asm/mach-types.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/time.h> + +#include <mach/clock.h> + +#include "common.h" + +#define XI_FREQUENCY 12000000 +#define XTI_FREQUENCY 32768 + +#ifdef CONFIG_MTD_NAND_TCC +/* NAND */ +static struct tcc_nand_platform_data tcc8k_sdk_nand_data = { + .width = 1, + .hw_ecc = 0, +}; +#endif + +static void __init tcc8k_init(void) +{ +#ifdef CONFIG_MTD_NAND_TCC + tcc_nand_device.dev.platform_data = &tcc8k_sdk_nand_data; + platform_device_register(&tcc_nand_device); +#endif +} + +static void __init tcc8k_init_timer(void) +{ + tcc_clocks_init(XI_FREQUENCY, XTI_FREQUENCY); +} + +static struct sys_timer tcc8k_timer = { + .init = tcc8k_init_timer, +}; + +static void __init tcc8k_map_io(void) +{ + tcc8k_map_common_io(); +} + +MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board") + .phys_io = 0x90000000, + .io_pg_offst = ((0xf1000000) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x00000100, + .map_io = tcc8k_map_io, + .init_irq = tcc8k_init_irq, + .init_machine = tcc8k_init, + .timer = &tcc8k_timer, +MACHINE_END diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c new file mode 100644 index 0000000..ba32a15 --- /dev/null +++ b/arch/arm/mach-tcc8k/clock.c @@ -0,0 +1,567 @@ +/* + * Lowlevel clock handling for Telechips TCC8xxx SoCs + * + * Copyright (C) 2010 by Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GPL v2 + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/spinlock.h> + +#include <asm/clkdev.h> + +#include <mach/clock.h> +#include <mach/irqs.h> +#include <mach/tcc8k-regs.h> + +#include "common.h" + +#define BCLKCTR0 (CKC_BASE + BCLKCTR0_OFFS) +#define BCLKCTR1 (CKC_BASE + BCLKCTR1_OFFS) + +#define ACLKREF (CKC_BASE + ACLKREF_OFFS) +#define ACLKUART0 (CKC_BASE + ACLKUART0_OFFS) +#define ACLKUART1 (CKC_BASE + ACLKUART1_OFFS) +#define ACLKUART2 (CKC_BASE + ACLKUART2_OFFS) +#define ACLKUART3 (CKC_BASE + ACLKUART3_OFFS) +#define ACLKUART4 (CKC_BASE + ACLKUART4_OFFS) +#define ACLKI2C (CKC_BASE + ACLKI2C_OFFS) +#define ACLKADC (CKC_BASE + ACLKADC_OFFS) +#define ACLKUSBH (CKC_BASE + ACLKUSBH_OFFS) +#define ACLKLCD (CKC_BASE + ACLKLCD_OFFS) +#define ACLKSDH0 (CKC_BASE + ACLKSDH0_OFFS) +#define ACLKSDH1 (CKC_BASE + ACLKSDH1_OFFS) +#define ACLKSPI0 (CKC_BASE + ACLKSPI0_OFFS) +#define ACLKSPI1 (CKC_BASE + ACLKSPI1_OFFS) +#define ACLKSPDIF (CKC_BASE + ACLKSPDIF_OFFS) +#define ACLKC3DEC (CKC_BASE + ACLKC3DEC_OFFS) +#define ACLKCAN0 (CKC_BASE + ACLKCAN0_OFFS) +#define ACLKCAN1 (CKC_BASE + ACLKCAN1_OFFS) +#define ACLKGSB0 (CKC_BASE + ACLKGSB0_OFFS) +#define ACLKGSB1 (CKC_BASE + ACLKGSB1_OFFS) +#define ACLKGSB2 (CKC_BASE + ACLKGSB2_OFFS) +#define ACLKGSB3 (CKC_BASE + ACLKGSB3_OFFS) +#define ACLKUSBH (CKC_BASE + ACLKUSBH_OFFS) +#define ACLKTCT (CKC_BASE + ACLKTCT_OFFS) +#define ACLKTCX (CKC_BASE + ACLKTCX_OFFS) +#define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS) + +/* Crystal frequencies */ +static unsigned long xi_rate, xti_rate; + +static void __iomem *pll_cfg_addr(int pll) +{ + switch (pll) { + case 0: return (CKC_BASE + PLL0CFG_OFFS); + case 1: return (CKC_BASE + PLL1CFG_OFFS); + case 2: return (CKC_BASE + PLL2CFG_OFFS); + default: + BUG(); + } +} + +static int pll_enable(int pll, int enable) +{ + u32 reg; + void __iomem *addr = pll_cfg_addr(pll); + + reg = __raw_readl(addr); + if (enable) + reg &= ~PLLxCFG_PD; + else + reg |= PLLxCFG_PD; + + __raw_writel(reg, addr); + return 0; +} + +static int xi_enable(int enable) +{ + u32 reg; + + reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS); + if (enable) + reg |= CLKCTRL_XE; + else + reg &= ~CLKCTRL_XE; + + __raw_writel(reg, CKC_BASE + CLKCTRL_OFFS); + return 0; +} + +static int root_clk_enable(enum root_clks src) +{ + switch (src) { + case CLK_SRC_PLL0: return pll_enable(0, 1); + case CLK_SRC_PLL1: return pll_enable(1, 1); + case CLK_SRC_PLL2: return pll_enable(2, 1); + case CLK_SRC_XI: return xi_enable(1); + default: + BUG(); + } + return 0; +} + +static int root_clk_disable(enum root_clks root_src) +{ + switch (root_src) { + case CLK_SRC_PLL0: return pll_enable(0, 0); + case CLK_SRC_PLL1: return pll_enable(1, 0); + case CLK_SRC_PLL2: return pll_enable(2, 0); + case CLK_SRC_XI: return xi_enable(0); + default: + BUG(); + } + return 0; +} + +static int enable_clk(struct clk *clk) +{ + u32 reg; + + if (clk->root_id != CLK_SRC_NOROOT) + return root_clk_enable(clk->root_id); + + if (clk->aclkreg) { + reg = __raw_readl(clk->aclkreg); + reg |= ACLK_EN; + __raw_writel(reg, clk->aclkreg); + } + if (clk->bclkctr) { + reg = __raw_readl(clk->bclkctr); + reg |= 1 << clk->bclk_shift; + __raw_writel(reg, clk->bclkctr); + } + return 0; +} + +static void disable_clk(struct clk *clk) +{ + u32 reg; + + if (clk->root_id != CLK_SRC_NOROOT) { + root_clk_disable(clk->root_id); + return; + } + + if (clk->bclkctr) { + reg = __raw_readl(clk->bclkctr); + reg &= ~(1 << clk->bclk_shift); + __raw_writel(reg, clk->bclkctr); + } + if (clk->aclkreg) { + reg = __raw_readl(clk->aclkreg); + reg &= ~ACLK_EN; + __raw_writel(reg, clk->aclkreg); + } +} + +static unsigned long get_rate_pll(int pll) +{ + u32 reg; + unsigned long s, m, p; + void __iomem *addr = pll_cfg_addr(pll); + + reg = __raw_readl(addr); + s = (reg >> 16) & 0x07; + m = (reg >> 8) & 0xff; + p = reg & 0x3f; + + return (m * xi_rate) / (p * (1 << s)); +} + +static unsigned long get_rate_pll_div(int pll) +{ + u32 reg; + unsigned long div = 0; + void __iomem *addr; + + switch (pll) { + case 0: + addr = CKC_BASE + CLKDIVC0_OFFS; + reg = __raw_readl(addr); + if (reg & CLKDIVC0_P0E) + div = (reg >> 24) & 0x3f; + break; + case 1: + addr = CKC_BASE + CLKDIVC0_OFFS; + reg = __raw_readl(addr); + if (reg & CLKDIVC0_P1E) + div = (reg >> 16) & 0x3f; + break; + case 2: + addr = CKC_BASE + CLKDIVC1_OFFS; + reg = __raw_readl(addr); + if (reg & CLKDIVC1_P2E) + div = __raw_readl(addr) & 0x3f; + break; + } + return get_rate_pll(pll) / (div + 1); +} + +static unsigned long get_rate_xi_div(void) +{ + unsigned long div = 0; + u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS); + + if (reg & CLKDIVC0_XE) + div = (reg >> 8) & 0x3f; + + return xi_rate / (div + 1); +} + +static unsigned long get_rate_xti_div(void) +{ + unsigned long div = 0; + u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS); + + if (reg & CLKDIVC0_XTE) + div = reg & 0x3f; + + return xti_rate / (div + 1); +} + +static unsigned long root_clk_get_rate(enum root_clks src) +{ + switch (src) { + case CLK_SRC_PLL0: return get_rate_pll(0); + case CLK_SRC_PLL1: return get_rate_pll(1); + case CLK_SRC_PLL2: return get_rate_pll(2); + case CLK_SRC_PLL0DIV: return get_rate_pll_div(0); + case CLK_SRC_PLL1DIV: return get_rate_pll_div(1); + case CLK_SRC_PLL2DIV: return get_rate_pll_div(2); + case CLK_SRC_XI: return xi_rate; + case CLK_SRC_XTI: return xti_rate; + case CLK_SRC_XIDIV: return get_rate_xi_div(); + case CLK_SRC_XTIDIV: return get_rate_xti_div(); + default: return 0; + } +} + +static unsigned long aclk_get_rate(struct clk *clk) +{ + u32 reg; + unsigned long div; + unsigned int src; + + reg = __raw_readl(clk->aclkreg); + div = reg & 0x0fff; + src = (reg >> ACLK_SEL_SHIFT) & CLK_SRC_MASK; + return root_clk_get_rate(src) / (div + 1); +} + +static unsigned long aclk_best_div(struct clk *clk, unsigned long rate) +{ + unsigned long div, src, freq, r1, r2; + + src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; + src &= CLK_SRC_MASK; + freq = root_clk_get_rate(src); + div = freq / rate + 1; + r1 = freq / div; + r2 = freq / (div + 1); + if (r2 >= rate) + return div + 1; + if ((rate - r2) < (r1 - rate)) + return div + 1; + + return div; +} + +static unsigned long aclk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned int src; + + src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; + src &= CLK_SRC_MASK; + + return root_clk_get_rate(src) / aclk_best_div(clk, rate); +} + +static int aclk_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + + reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK; + reg |= aclk_best_div(clk, rate); + return 0; +} + +static unsigned long get_rate_sys(struct clk *clk) +{ + unsigned int src; + + src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK; + return root_clk_get_rate(src); +} + +static unsigned long get_rate_bus(struct clk *clk) +{ + unsigned int div; + + div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff; + return get_rate_sys(clk) / (div + 1); +} + +static unsigned long get_rate_cpu(struct clk *clk) +{ + unsigned int reg, div, fsys, fbus; + + fbus = get_rate_bus(clk); + reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS); + if (reg & (1 << 29)) + return fbus; + fsys = get_rate_sys(clk); + div = (reg >> 16) & 0x0f; + return fbus + ((fsys - fbus) * (div + 1)) / 16; +} + +static unsigned long get_rate_root(struct clk *clk) +{ + return root_clk_get_rate(clk->root_id); +} + +static int aclk_set_parent(struct clk *clock, struct clk *parent) +{ + u32 reg; + + if (clock->parent == parent) + return 0; + + clock->parent = parent; + + if (!parent) + return 0; + + if (parent->root_id == CLK_SRC_NOROOT) + return 0; + reg = __raw_readl(clock->aclkreg); + reg &= ~ACLK_SEL_MASK; + reg |= (parent->root_id << ACLK_SEL_SHIFT) & ACLK_SEL_MASK; + __raw_writel(reg, clock->aclkreg); + + return 0; +} + +#define DEFINE_ROOT_CLOCK(name, ri, p) \ + static struct clk name = { \ + .root_id = ri, \ + .get_rate = get_rate_root, \ + .enable = enable_clk, \ + .disable = disable_clk, \ + .parent = p, \ + }; + +#define DEFINE_SPECIAL_CLOCK(name, gr, p) \ + static struct clk name = { \ + .root_id = CLK_SRC_NOROOT, \ + .get_rate = gr, \ + .parent = p, \ + }; + +#define DEFINE_ACLOCK(name, bc, bs, ar) \ + static struct clk name = { \ + .root_id = CLK_SRC_NOROOT, \ + .bclkctr = bc, \ + .bclk_shift = bs, \ + .aclkreg = ar, \ + .get_rate = aclk_get_rate, \ + .set_rate = aclk_set_rate, \ + .round_rate = aclk_round_rate, \ + .enable = enable_clk, \ + .disable = disable_clk, \ + .set_parent = aclk_set_parent, \ + }; + +#define DEFINE_BCLOCK(name, bc, bs, gr, p) \ + static struct clk name = { \ + .root_id = CLK_SRC_NOROOT, \ + .bclkctr = bc, \ + .bclk_shift = bs, \ + .get_rate = gr, \ + .enable = enable_clk, \ + .disable = disable_clk, \ + .parent = p, \ + }; + +DEFINE_ROOT_CLOCK(xi, CLK_SRC_XI, NULL) +DEFINE_ROOT_CLOCK(xti, CLK_SRC_XTI, NULL) +DEFINE_ROOT_CLOCK(xidiv, CLK_SRC_XIDIV, &xi) +DEFINE_ROOT_CLOCK(xtidiv, CLK_SRC_XTIDIV, &xti) +DEFINE_ROOT_CLOCK(pll0, CLK_SRC_PLL0, &xi) +DEFINE_ROOT_CLOCK(pll1, CLK_SRC_PLL1, &xi) +DEFINE_ROOT_CLOCK(pll2, CLK_SRC_PLL2, &xi) +DEFINE_ROOT_CLOCK(pll0div, CLK_SRC_PLL0DIV, &pll0) +DEFINE_ROOT_CLOCK(pll1div, CLK_SRC_PLL1DIV, &pll1) +DEFINE_ROOT_CLOCK(pll2div, CLK_SRC_PLL2DIV, &pll2) + +/* The following 3 clocks are special and are initialized explicitly later */ +DEFINE_SPECIAL_CLOCK(sys, get_rate_sys, NULL) +DEFINE_SPECIAL_CLOCK(bus, get_rate_bus, &sys) +DEFINE_SPECIAL_CLOCK(cpu, get_rate_cpu, &sys) + +DEFINE_ACLOCK(tct, NULL, 0, ACLKTCT) +DEFINE_ACLOCK(tcx, NULL, 0, ACLKTCX) +DEFINE_ACLOCK(tcz, NULL, 0, ACLKTCZ) +DEFINE_ACLOCK(ref, NULL, 0, ACLKREF) +DEFINE_ACLOCK(uart0, BCLKCTR0, 5, ACLKUART0) +DEFINE_ACLOCK(uart1, BCLKCTR0, 23, ACLKUART1) +DEFINE_ACLOCK(uart2, BCLKCTR0, 6, ACLKUART2) +DEFINE_ACLOCK(uart3, BCLKCTR0, 8, ACLKUART3) +DEFINE_ACLOCK(uart4, BCLKCTR1, 6, ACLKUART4) +DEFINE_ACLOCK(i2c, BCLKCTR0, 7, ACLKI2C) +DEFINE_ACLOCK(adc, BCLKCTR0, 10, ACLKADC) +DEFINE_ACLOCK(usbh0, BCLKCTR0, 11, ACLKUSBH) +DEFINE_ACLOCK(lcd, BCLKCTR0, 13, ACLKLCD) +DEFINE_ACLOCK(sd0, BCLKCTR0, 17, ACLKSDH0) +DEFINE_ACLOCK(sd1, BCLKCTR1, 5, ACLKSDH1) +DEFINE_ACLOCK(spi0, BCLKCTR0, 24, ACLKSPI0) +DEFINE_ACLOCK(spi1, BCLKCTR0, 30, ACLKSPI1) +DEFINE_ACLOCK(spdif, BCLKCTR1, 2, ACLKSPDIF) +DEFINE_ACLOCK(c3dec, BCLKCTR1, 9, ACLKC3DEC) +DEFINE_ACLOCK(can0, BCLKCTR1, 10, ACLKCAN0) +DEFINE_ACLOCK(can1, BCLKCTR1, 11, ACLKCAN1) +DEFINE_ACLOCK(gsb0, BCLKCTR1, 13, ACLKGSB0) +DEFINE_ACLOCK(gsb1, BCLKCTR1, 14, ACLKGSB1) +DEFINE_ACLOCK(gsb2, BCLKCTR1, 15, ACLKGSB2) +DEFINE_ACLOCK(gsb3, BCLKCTR1, 16, ACLKGSB3) +DEFINE_ACLOCK(usbh1, BCLKCTR1, 20, ACLKUSBH) + +DEFINE_BCLOCK(dai0, BCLKCTR0, 0, NULL, NULL) +DEFINE_BCLOCK(pic, BCLKCTR0, 1, NULL, NULL) +DEFINE_BCLOCK(tc, BCLKCTR0, 2, NULL, NULL) +DEFINE_BCLOCK(gpio, BCLKCTR0, 3, NULL, NULL) +DEFINE_BCLOCK(usbd, BCLKCTR0, 4, NULL, NULL) +DEFINE_BCLOCK(ecc, BCLKCTR0, 9, NULL, NULL) +DEFINE_BCLOCK(gdma0, BCLKCTR0, 12, NULL, NULL) +DEFINE_BCLOCK(rtc, BCLKCTR0, 15, NULL, NULL) +DEFINE_BCLOCK(nfc, BCLKCTR0, 16, NULL, NULL) +DEFINE_BCLOCK(g2d, BCLKCTR0, 18, NULL, NULL) +DEFINE_BCLOCK(gdma1, BCLKCTR0, 22, NULL, NULL) +DEFINE_BCLOCK(mscl, BCLKCTR0, 25, NULL, NULL) +DEFINE_BCLOCK(bdma, BCLKCTR1, 0, NULL, NULL) +DEFINE_BCLOCK(adma0, BCLKCTR1, 1, NULL, NULL) +DEFINE_BCLOCK(scfg, BCLKCTR1, 3, NULL, NULL) +DEFINE_BCLOCK(cid, BCLKCTR1, 4, NULL, NULL) +DEFINE_BCLOCK(dai1, BCLKCTR1, 7, NULL, NULL) +DEFINE_BCLOCK(adma1, BCLKCTR1, 8, NULL, NULL) +DEFINE_BCLOCK(gps, BCLKCTR1, 12, NULL, NULL) +DEFINE_BCLOCK(gdma2, BCLKCTR1, 17, NULL, NULL) +DEFINE_BCLOCK(gdma3, BCLKCTR1, 18, NULL, NULL) +DEFINE_BCLOCK(ddrc, BCLKCTR1, 19, NULL, NULL) + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] = { + _REGISTER_CLOCK(NULL, "bus", bus) + _REGISTER_CLOCK(NULL, "cpu", cpu) + _REGISTER_CLOCK(NULL, "tct", tct) + _REGISTER_CLOCK(NULL, "tcx", tcx) + _REGISTER_CLOCK(NULL, "tcz", tcz) + _REGISTER_CLOCK(NULL, "ref", ref) + _REGISTER_CLOCK(NULL, "dai0", dai0) + _REGISTER_CLOCK(NULL, "pic", pic) + _REGISTER_CLOCK(NULL, "tc", tc) + _REGISTER_CLOCK(NULL, "gpio", gpio) + _REGISTER_CLOCK(NULL, "usbd", usbd) + _REGISTER_CLOCK("tcc-uart.0", NULL, uart0) + _REGISTER_CLOCK("tcc-uart.2", NULL, uart2) + _REGISTER_CLOCK("tcc-i2c", NULL, i2c) + _REGISTER_CLOCK("tcc-uart.3", NULL, uart3) + _REGISTER_CLOCK(NULL, "ecc", ecc) + _REGISTER_CLOCK(NULL, "adc", adc) + _REGISTER_CLOCK("tcc-usbh.0", "usb", usbh0) + _REGISTER_CLOCK(NULL, "gdma0", gdma0) + _REGISTER_CLOCK(NULL, "lcd", lcd) + _REGISTER_CLOCK(NULL, "rtc", rtc) + _REGISTER_CLOCK(NULL, "nfc", nfc) + _REGISTER_CLOCK("tcc-mmc.0", NULL, sd0) + _REGISTER_CLOCK(NULL, "g2d", g2d) + _REGISTER_CLOCK(NULL, "gdma1", gdma1) + _REGISTER_CLOCK("tcc-uart.1", NULL, uart1) + _REGISTER_CLOCK("tcc-spi.0", NULL, spi0) + _REGISTER_CLOCK(NULL, "mscl", mscl) + _REGISTER_CLOCK("tcc-spi.1", NULL, spi1) + _REGISTER_CLOCK(NULL, "bdma", bdma) + _REGISTER_CLOCK(NULL, "adma0", adma0) + _REGISTER_CLOCK(NULL, "spdif", spdif) + _REGISTER_CLOCK(NULL, "scfg", scfg) + _REGISTER_CLOCK(NULL, "cid", cid) + _REGISTER_CLOCK("tcc-mmc.1", NULL, sd1) + _REGISTER_CLOCK("tcc-uart.4", NULL, uart4) + _REGISTER_CLOCK(NULL, "dai1", dai1) + _REGISTER_CLOCK(NULL, "adma1", adma1) + _REGISTER_CLOCK(NULL, "c3dec", c3dec) + _REGISTER_CLOCK("tcc-can.0", NULL, can0) + _REGISTER_CLOCK("tcc-can.1", NULL, can1) + _REGISTER_CLOCK(NULL, "gps", gps) + _REGISTER_CLOCK("tcc-gsb.0", NULL, gsb0) + _REGISTER_CLOCK("tcc-gsb.1", NULL, gsb1) + _REGISTER_CLOCK("tcc-gsb.2", NULL, gsb2) + _REGISTER_CLOCK("tcc-gsb.3", NULL, gsb3) + _REGISTER_CLOCK(NULL, "gdma2", gdma2) + _REGISTER_CLOCK(NULL, "gdma3", gdma3) + _REGISTER_CLOCK(NULL, "ddrc", ddrc) + _REGISTER_CLOCK("tcc-usbh.1", "usb", usbh1) +}; + +static struct clk *root_clk_by_index(enum root_clks src) +{ + switch (src) { + case CLK_SRC_PLL0: return &pll0; + case CLK_SRC_PLL1: return &pll1; + case CLK_SRC_PLL2: return &pll2; + case CLK_SRC_PLL0DIV: return &pll0div; + case CLK_SRC_PLL1DIV: return &pll1div; + case CLK_SRC_PLL2DIV: return &pll2div; + case CLK_SRC_XI: return ξ + case CLK_SRC_XTI: return &xti; + case CLK_SRC_XIDIV: return &xidiv; + case CLK_SRC_XTIDIV: return &xtidiv; + default: return NULL; + } +} + +static void find_aclk_parent(struct clk *clk) +{ + unsigned int src; + struct clk *clock; + + if (!clk->aclkreg) + return; + + src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; + src &= CLK_SRC_MASK; + + clock = root_clk_by_index(src); + if (!clock) + return; + + clk->parent = clock; + clk->set_parent = aclk_set_parent; +} + +void __init tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq) +{ + int i; + + xi_rate = xi_freq; + xti_rate = xti_freq; + + /* fixup parents and add the clock */ + for (i = 0; i < ARRAY_SIZE(lookups); i++) { + find_aclk_parent(lookups[i].clk); + clkdev_add(&lookups[i]); + } + tcc8k_timer_init(&tcz, (void __iomem *)TIMER_BASE, INT_TC32); +} diff --git a/arch/arm/mach-tcc8k/common.h b/arch/arm/mach-tcc8k/common.h new file mode 100644 index 0000000..705690a --- /dev/null +++ b/arch/arm/mach-tcc8k/common.h @@ -0,0 +1,15 @@ +#ifndef MACH_TCC8K_COMMON_H +#define MACH_TCC8K_COMMON_H + +#include <linux/platform_device.h> + +extern struct platform_device tcc_nand_device; + +struct clk; + +extern void tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq); +extern void tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq); +extern void tcc8k_init_irq(void); +extern void tcc8k_map_common_io(void); + +#endif diff --git a/arch/arm/mach-tcc8k/devices.c b/arch/arm/mach-tcc8k/devices.c new file mode 100644 index 0000000..6722ad7 --- /dev/null +++ b/arch/arm/mach-tcc8k/devices.c @@ -0,0 +1,239 @@ +/* + * linux/arch/arm/mach-tcc8k/devices.c + * + * Copyright (C) Telechips, Inc. + * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of GPL v2. + * + */ + +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include <asm/mach/map.h> + +#include <mach/tcc8k-regs.h> +#include <mach/irqs.h> + +#include "common.h" + +static u64 tcc8k_dmamask = DMA_BIT_MASK(32); + +#ifdef CONFIG_MTD_NAND_TCC +/* NAND controller */ +static struct resource tcc_nand_resources[] = { + { + .start = (resource_size_t)NFC_BASE, + .end = (resource_size_t)NFC_BASE + 0x7f, + .flags = IORESOURCE_MEM, + }, { + .start = INT_NFC, + .end = INT_NFC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device tcc_nand_device = { + .name = "tcc_nand", + .id = 0, + .num_resources = ARRAY_SIZE(tcc_nand_resources), + .resource = tcc_nand_resources, +}; +#endif + +#ifdef CONFIG_MMC_TCC8K +/* MMC controller */ +static struct resource tcc8k_mmc0_resource[] = { + { + .start = INT_SD0, + .end = INT_SD0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource tcc8k_mmc1_resource[] = { + { + .start = INT_SD1, + .end = INT_SD1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device tcc8k_mmc0_device = { + .name = "tcc-mmc", + .id = 0, + .num_resources = ARRAY_SIZE(tcc8k_mmc0_resource), + .resource = tcc8k_mmc0_resource, + .dev = { + .dma_mask = &tcc8k_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + } +}; + +struct platform_device tcc8k_mmc1_device = { + .name = "tcc-mmc", + .id = 1, + .num_resources = ARRAY_SIZE(tcc8k_mmc1_resource), + .resource = tcc8k_mmc1_resource, + .dev = { + .dma_mask = &tcc8k_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + } +}; + +static inline void tcc8k_init_mmc(void) +{ + u32 reg = __raw_readl(GPIOPS_BASE + GPIOPS_FS1_OFFS); + + reg |= GPIOPS_FS1_SDH0_BITS | GPIOPS_FS1_SDH1_BITS; + __raw_writel(reg, GPIOPS_BASE + GPIOPS_FS1_OFFS); + + platform_device_register(&tcc8k_mmc0_device); + platform_device_register(&tcc8k_mmc1_device); +} +#else +static inline void tcc8k_init_mmc(void) { } +#endif + +#ifdef CONFIG_USB_OHCI_HCD +static int tcc8k_ohci_init(struct device *dev) +{ + u32 reg; + + /* Use GPIO PK19 as VBUS control output */ + reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS0_OFFS); + reg &= ~(1 << 19); + __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS0_OFFS); + reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS1_OFFS); + reg &= ~(1 << 19); + __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS1_OFFS); + + reg = __raw_readl(GPIOPK_BASE + GPIOPK_DOE_OFFS); + reg |= (1 << 19); + __raw_writel(reg, GPIOPK_BASE + GPIOPK_DOE_OFFS); + /* Turn on VBUS */ + reg = __raw_readl(GPIOPK_BASE + GPIOPK_DAT_OFFS); + reg |= (1 << 19); + __raw_writel(reg, GPIOPK_BASE + GPIOPK_DAT_OFFS); + + return 0; +} + +static struct resource tcc8k_ohci0_resources[] = { + [0] = { + .start = (resource_size_t)USBH0_BASE, + .end = (resource_size_t)USBH0_BASE + 0x5c, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = INT_USBH0, + .end = INT_USBH0, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource tcc8k_ohci1_resources[] = { + [0] = { + .start = (resource_size_t)USBH1_BASE, + .end = (resource_size_t)USBH1_BASE + 0x5c, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = INT_USBH1, + .end = INT_USBH1, + .flags = IORESOURCE_IRQ, + } +}; + +static struct tccohci_platform_data tcc8k_ohci0_platform_data = { + .controller = 0, + .port_mode = PMM_PERPORT_MODE, + .init = tcc8k_ohci_init, +}; + +static struct tccohci_platform_data tcc8k_ohci1_platform_data = { + .controller = 1, + .port_mode = PMM_PERPORT_MODE, + .init = tcc8k_ohci_init, +}; + +static struct platform_device ohci0_device = { + .name = "tcc-ohci", + .id = 0, + .dev = { + .dma_mask = &tcc8k_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &tcc8k_ohci0_platform_data, + }, + .num_resources = ARRAY_SIZE(tcc8k_ohci0_resources), + .resource = tcc8k_ohci0_resources, +}; + +static struct platform_device ohci1_device = { + .name = "tcc-ohci", + .id = 1, + .dev = { + .dma_mask = &tcc8k_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &tcc8k_ohci1_platform_data, + }, + .num_resources = ARRAY_SIZE(tcc8k_ohci1_resources), + .resource = tcc8k_ohci1_resources, +}; + +static void __init tcc8k_init_usbhost(void) +{ + platform_device_register(&ohci0_device); + platform_device_register(&ohci1_device); +} +#else +static void __init tcc8k_init_usbhost(void) { } +#endif + +/* USB device controller*/ +#ifdef CONFIG_USB_GADGET_TCC8K +static struct resource udc_resources[] = { + [0] = { + .start = INT_USBD, + .end = INT_USBD, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = INT_UDMA, + .end = INT_UDMA, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tcc8k_udc_device = { + .name = "tcc-udc", + .id = 0, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), + .dev = { + .dma_mask = &tcc8k_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +static void __init tcc8k_init_usb_gadget(void) +{ + platform_device_register(&tcc8k_udc_device); +} +#else +static void __init tcc8k_init_usb_gadget(void) { } +#endif /* CONFIG_USB_GADGET_TCC83X */ + +static int __init tcc8k_init_devices(void) +{ + tcc8k_init_mmc(); + tcc8k_init_usbhost(); + tcc8k_init_usb_gadget(); + return 0; +} + +arch_initcall(tcc8k_init_devices); diff --git a/arch/arm/mach-tcc8k/io.c b/arch/arm/mach-tcc8k/io.c new file mode 100644 index 0000000..9b39d7f --- /dev/null +++ b/arch/arm/mach-tcc8k/io.c @@ -0,0 +1,62 @@ +/* + * linux/arch/arm/mach-tcc8k/io.c + * + * (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * derived from TCC83xx io.c + * Copyright (C) Telechips, Inc. + * + * 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/init.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include <asm/mach/map.h> + +#include <mach/tcc8k-regs.h> + +/* + * The machine specific code may provide the extra mapping besides the + * default mapping provided here. + */ +static struct map_desc tcc8k_io_desc[] __initdata = { + { + .virtual = (unsigned long)CS1_BASE_VIRT, + .pfn = __phys_to_pfn(CS1_BASE), + .length = CS1_SIZE, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)AHB_PERI_BASE_VIRT, + .pfn = __phys_to_pfn(AHB_PERI_BASE), + .length = AHB_PERI_SIZE, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)APB0_PERI_BASE_VIRT, + .pfn = __phys_to_pfn(APB0_PERI_BASE), + .length = APB0_PERI_SIZE, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)APB1_PERI_BASE_VIRT, + .pfn = __phys_to_pfn(APB1_PERI_BASE), + .length = APB1_PERI_SIZE, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)EXT_MEM_CTRL_BASE_VIRT, + .pfn = __phys_to_pfn(EXT_MEM_CTRL_BASE), + .length = EXT_MEM_CTRL_SIZE, + .type = MT_DEVICE, + }, +}; + +/* + * Maps common IO regions for tcc8k. + * + */ +void __init tcc8k_map_common_io(void) +{ + iotable_init(tcc8k_io_desc, ARRAY_SIZE(tcc8k_io_desc)); +} diff --git a/arch/arm/mach-tcc8k/irq.c b/arch/arm/mach-tcc8k/irq.c new file mode 100644 index 0000000..34575c4 --- /dev/null +++ b/arch/arm/mach-tcc8k/irq.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) Telechips, Inc. + * Copyright (C) 2009-2010 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GNU GPL version 2. + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> + +#include <asm/irq.h> +#include <asm/mach/irq.h> + +#include <mach/tcc8k-regs.h> +#include <mach/irqs.h> + +#include "common.h" + +/* Disable IRQ */ +static void tcc8000_mask_ack_irq0(unsigned int irq) +{ + PIC0_IEN &= ~(1 << irq); + PIC0_CREQ |= (1 << irq); +} + +static void tcc8000_mask_ack_irq1(unsigned int irq) +{ + PIC1_IEN &= ~(1 << (irq - 32)); + PIC1_CREQ |= (1 << (irq - 32)); +} + +static void tcc8000_mask_irq0(unsigned int irq) +{ + PIC0_IEN &= ~(1 << irq); +} + +static void tcc8000_mask_irq1(unsigned int irq) +{ + PIC1_IEN &= ~(1 << (irq - 32)); +} + +static void tcc8000_ack_irq0(unsigned int irq) +{ + PIC0_CREQ |= (1 << irq); +} + +static void tcc8000_ack_irq1(unsigned int irq) +{ + PIC1_CREQ |= (1 << (irq - 32)); +} + +/* Enable IRQ */ +static void tcc8000_unmask_irq0(unsigned int irq) +{ + PIC0_IEN |= (1 << irq); + PIC0_INTOEN |= (1 << irq); +} + +static void tcc8000_unmask_irq1(unsigned int irq) +{ + PIC1_IEN |= (1 << (irq - 32)); + PIC1_INTOEN |= (1 << (irq - 32)); +} + +static struct irq_chip tcc8000_irq_chip0 = { + .name = "tcc_irq0", + .mask = tcc8000_mask_irq0, + .ack = tcc8000_ack_irq0, + .mask_ack = tcc8000_mask_ack_irq0, + .unmask = tcc8000_unmask_irq0, +}; + +static struct irq_chip tcc8000_irq_chip1 = { + .name = "tcc_irq1", + .mask = tcc8000_mask_irq1, + .ack = tcc8000_ack_irq1, + .mask_ack = tcc8000_mask_ack_irq1, + .unmask = tcc8000_unmask_irq1, +}; + +void __init tcc8k_init_irq(void) +{ + int irqno; + + /* Mask and clear all interrupts */ + PIC0_IEN = 0x00000000; + PIC0_CREQ = 0xffffffff; + PIC1_IEN = 0x00000000; + PIC1_CREQ = 0xffffffff; + + PIC0_MEN0 = 0x00000003; + PIC1_MEN1 = 0x00000003; + PIC1_MEN = 0x00000003; + + /* let all IRQs be level triggered */ + PIC0_TMODE = 0xffffffff; + PIC1_TMODE = 0xffffffff; + /* all IRQs are IRQs (not FIQs) */ + PIC0_IRQSEL = 0xffffffff; + PIC1_IRQSEL = 0xffffffff; + + for (irqno = 0; irqno < NR_IRQS; irqno++) { + if (irqno < 32) + set_irq_chip(irqno, &tcc8000_irq_chip0); + else + set_irq_chip(irqno, &tcc8000_irq_chip1); + set_irq_handler(irqno, handle_level_irq); + set_irq_flags(irqno, IRQF_VALID); + } +} diff --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c new file mode 100644 index 0000000..78d0600 --- /dev/null +++ b/arch/arm/mach-tcc8k/time.c @@ -0,0 +1,149 @@ +/* + * TCC8000 system timer setup + * + * (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GPL version 2. + * + */ + +#include <linux/clk.h> +#include <linux/clockchips.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> + +#include <asm/mach/time.h> + +#include <mach/tcc8k-regs.h> +#include <mach/irqs.h> + +#include "common.h" + +static void __iomem *timer_base; + +static cycle_t tcc_get_cycles(struct clocksource *cs) +{ + return __raw_readl(timer_base + TC32MCNT_OFFS); +} + +static struct clocksource clocksource_tcc = { + .name = "tcc_tc32", + .rating = 200, + .read = tcc_get_cycles, + .mask = CLOCKSOURCE_MASK(32), + .shift = 28, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int tcc_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + unsigned long reg = __raw_readl(timer_base + TC32MCNT_OFFS); + + __raw_writel(reg + evt, timer_base + TC32CMP0_OFFS); + return 0; +} + +static void tcc_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + unsigned long tc32irq; + + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS); + tc32irq |= TC32IRQ_IRQEN0; + __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS); + tc32irq &= ~TC32IRQ_IRQEN0; + __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS); + break; + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static irqreturn_t tcc8k_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + /* Acknowledge TC32 interrupt by reading TC32IRQ */ + __raw_readl(timer_base + TC32IRQ_OFFS); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct clock_event_device clockevent_tcc = { + .name = "tcc_timer1", + .features = CLOCK_EVT_FEAT_ONESHOT, + .shift = 32, + .set_mode = tcc_set_mode, + .set_next_event = tcc_set_next_event, + .rating = 200, +}; + +static struct irqaction tcc8k_timer_irq = { + .name = "TC32_timer", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = tcc8k_timer_interrupt, + .dev_id = &clockevent_tcc, +}; + +static int __init tcc_clockevent_init(struct clk *clock) +{ + unsigned int c = clk_get_rate(clock); + + clocksource_tcc.mult = clocksource_hz2mult(c, + clocksource_tcc.shift); + clocksource_register(&clocksource_tcc); + + clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC, + clockevent_tcc.shift); + clockevent_tcc.max_delta_ns = + clockevent_delta2ns(0xfffffffe, &clockevent_tcc); + clockevent_tcc.min_delta_ns = + clockevent_delta2ns(0xff, &clockevent_tcc); + + clockevent_tcc.cpumask = cpumask_of(0); + + clockevents_register_device(&clockevent_tcc); + + return 0; +} + +void __init tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq) +{ + u32 reg; + + timer_base = base; + tcc8k_timer_irq.irq = irq; + + /* Enable clocks */ + clk_enable(clock); + + /* Initialize 32-bit timer */ + reg = __raw_readl(timer_base + TC32EN_OFFS); + reg &= ~TC32EN_ENABLE; /* Disable timer */ + __raw_writel(reg, timer_base + TC32EN_OFFS); + /* Free running timer, counting from 0 to 0xffffffff */ + __raw_writel(0, timer_base + TC32EN_OFFS); + __raw_writel(0, timer_base + TC32LDV_OFFS); + reg = __raw_readl(timer_base + TC32IRQ_OFFS); + reg |= TC32IRQ_IRQEN0; /* irq at match with CMP0 */ + __raw_writel(reg, timer_base + TC32IRQ_OFFS); + + __raw_writel(TC32EN_ENABLE, timer_base + TC32EN_OFFS); + + tcc_clockevent_init(clock); + setup_irq(irq, &tcc8k_timer_irq); +} diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h index 7b1fc98..d5a71ab 100644 --- a/arch/arm/mach-u300/include/mach/gpio.h +++ b/arch/arm/mach-u300/include/mach/gpio.h @@ -273,6 +273,9 @@ extern void gpio_pullup(unsigned gpio, int value); extern int gpio_get_value(unsigned gpio); extern void gpio_set_value(unsigned gpio, int value); +#define gpio_get_value_cansleep gpio_get_value +#define gpio_set_value_cansleep gpio_set_value + /* wrappers to sleep-enable the previous two functions */ static inline unsigned gpio_to_irq(unsigned gpio) { diff --git a/arch/arm/mach-versatile/include/mach/vmalloc.h b/arch/arm/mach-versatile/include/mach/vmalloc.h index 427e361..ebd8a25 100644 --- a/arch/arm/mach-versatile/include/mach/vmalloc.h +++ b/arch/arm/mach-versatile/include/mach/vmalloc.h @@ -18,4 +18,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x18000000) +#define VMALLOC_END 0xd8000000 diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 577df6c..71fb173 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -68,7 +68,7 @@ static void __init ct_ca9x4_init_irq(void) } #if 0 -static void ct_ca9x4_timer_init(void) +static void __init ct_ca9x4_timer_init(void) { writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL); writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL); @@ -222,12 +222,18 @@ static struct platform_device pmu_device = { .resource = pmu_resources, }; -static void ct_ca9x4_init(void) +static void __init ct_ca9x4_init(void) { int i; #ifdef CONFIG_CACHE_L2X0 - l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00000000, 0xfe0fffff); + void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC); + + /* set RAM latencies to 1 cycle for this core tile. */ + writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); + writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); + + l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); #endif clkdev_add_table(lookups, ARRAY_SIZE(lookups)); diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 817f0ad..7eaa232 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -48,7 +48,7 @@ void __init v2m_map_io(struct map_desc *tile, size_t num) } -static void v2m_timer_init(void) +static void __init v2m_timer_init(void) { writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index d073b64..724ba3b 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -885,8 +885,23 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (ai_usermode & UM_SIGNAL) force_sig(SIGBUS, current); - else - set_cr(cr_no_alignment); + else { + /* + * We're about to disable the alignment trap and return to + * user space. But if an interrupt occurs before actually + * reaching user space, then the IRQ vector entry code will + * notice that we were still in kernel space and therefore + * the alignment trap won't be re-enabled in that case as it + * is presumed to be always on from kernel space. + * Let's prevent that race by disabling interrupts here (they + * are disabled on the way back to user space anyway in + * entry-common.S) and disable the alignment trap only if + * there is no work pending for this thread. + */ + raw_local_irq_disable(); + if (!(current_thread_info()->flags & _TIF_WORK_MASK)) + set_cr(cr_no_alignment); + } return 0; } diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index ab50627..17e7b0b 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -204,8 +204,12 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, /* * Don't allow RAM to be mapped - this causes problems with ARMv6+ */ - if (WARN_ON(pfn_valid(pfn))) - return NULL; + if (pfn_valid(pfn)) { + printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory. This leads\n" + KERN_WARNING "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n" + KERN_WARNING "will fail in the next kernel release. Please fix your driver.\n"); + WARN_ON(1); + } type = get_mem_type(mtype); if (!type) diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 4f5b396..b0a9830 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -144,3 +144,25 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) { return !(pfn + (size >> PAGE_SHIFT) > 0x00100000); } + +#ifdef CONFIG_STRICT_DEVMEM + +#include <linux/ioport.h> + +/* + * devmem_is_allowed() checks to see if /dev/mem access to a certain + * address is valid. The argument is a physical page number. + * We mimic x86 here by disallowing access to system RAM as well as + * device-exclusive MMIO regions. This effectively disable read()/write() + * on /dev/mem. + */ +int devmem_is_allowed(unsigned long pfn) +{ + if (iomem_is_exclusive(pfn << PAGE_SHIFT)) + return 0; + if (!page_is_ram(pfn)) + return 1; + return 0; +} + +#endif diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6e1c4f6..e8ed9dc 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -15,6 +15,7 @@ #include <linux/nodemask.h> #include <linux/memblock.h> #include <linux/sort.h> +#include <linux/fs.h> #include <asm/cputype.h> #include <asm/sections.h> @@ -246,6 +247,9 @@ static struct mem_type mem_types[] = { .domain = DOMAIN_USER, }, [MT_MEMORY] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_WRITE | L_PTE_EXEC, + .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, }, @@ -254,6 +258,9 @@ static struct mem_type mem_types[] = { .domain = DOMAIN_KERNEL, }, [MT_MEMORY_NONCACHED] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE, + .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, }, @@ -411,9 +418,12 @@ static void __init build_mem_type_table(void) * Enable CPU-specific coherency if supported. * (Only available on XSC3 at the moment.) */ - if (arch_is_coherent() && cpu_is_xsc3()) + if (arch_is_coherent() && cpu_is_xsc3()) { mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - + mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; + } /* * ARMv6 and above have extended page tables. */ @@ -438,7 +448,9 @@ static void __init build_mem_type_table(void) mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; #endif } @@ -475,6 +487,8 @@ static void __init build_mem_type_table(void) mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; + mem_types[MT_MEMORY].prot_pte |= kern_pgprot; + mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask; mem_types[MT_ROM].prot_sect |= cp->pmd; switch (cp->pmd) { @@ -498,6 +512,19 @@ static void __init build_mem_type_table(void) } } +#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot) +{ + if (!pfn_valid(pfn)) + return pgprot_noncached(vma_prot); + else if (file->f_flags & O_SYNC) + return pgprot_writecombine(vma_prot); + return vma_prot; +} +EXPORT_SYMBOL(phys_mem_access_prot); +#endif + #define vectors_base() (vectors_high() ? 0xffff0000 : 0) static void __init *early_alloc(unsigned long sz) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 6a8506d..197f21b 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -186,13 +186,14 @@ cpu_v7_name: * It is assumed that: * - cache type register is implemented */ -__v7_setup: +__v7_ca9mp_setup: #ifdef CONFIG_SMP mrc p15, 0, r0, c1, c0, 1 tst r0, #(1 << 6) @ SMP/nAMP mode enabled? orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting #endif +__v7_setup: adr r12, __v7_setup_stack @ the local stack stmia r12, {r0-r5, r7, r9, r11, lr} bl v7_flush_dcache_all @@ -201,11 +202,16 @@ __v7_setup: mrc p15, 0, r0, c0, c0, 0 @ read main ID register and r10, r0, #0xff000000 @ ARM? teq r10, #0x41000000 - bne 2f + bne 3f and r5, r0, #0x00f00000 @ variant and r6, r0, #0x0000000f @ revision - orr r0, r6, r5, lsr #20-4 @ combine variant and revision + orr r6, r6, r5, lsr #20-4 @ combine variant and revision + ubfx r0, r0, #4, #12 @ primary part number + /* Cortex-A8 Errata */ + ldr r10, =0x00000c08 @ Cortex-A8 primary part number + teq r0, r10 + bne 2f #ifdef CONFIG_ARM_ERRATA_430973 teq r5, #0x00100000 @ only present in r1p* mrceq p15, 0, r10, c1, c0, 1 @ read aux control register @@ -213,21 +219,50 @@ __v7_setup: mcreq p15, 0, r10, c1, c0, 1 @ write aux control register #endif #ifdef CONFIG_ARM_ERRATA_458693 - teq r0, #0x20 @ only present in r2p0 + teq r6, #0x20 @ only present in r2p0 mrceq p15, 0, r10, c1, c0, 1 @ read aux control register orreq r10, r10, #(1 << 5) @ set L1NEON to 1 orreq r10, r10, #(1 << 9) @ set PLDNOP to 1 mcreq p15, 0, r10, c1, c0, 1 @ write aux control register #endif #ifdef CONFIG_ARM_ERRATA_460075 - teq r0, #0x20 @ only present in r2p0 + teq r6, #0x20 @ only present in r2p0 mrceq p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register tsteq r10, #1 << 22 orreq r10, r10, #(1 << 22) @ set the Write Allocate disable bit mcreq p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register #endif + b 3f -2: mov r10, #0 + /* Cortex-A9 Errata */ +2: ldr r10, =0x00000c09 @ Cortex-A9 primary part number + teq r0, r10 + bne 3f +#ifdef CONFIG_ARM_ERRATA_742230 + cmp r6, #0x22 @ only present up to r2p2 + mrcle p15, 0, r10, c15, c0, 1 @ read diagnostic register + orrle r10, r10, #1 << 4 @ set bit #4 + mcrle p15, 0, r10, c15, c0, 1 @ write diagnostic register +#endif +#ifdef CONFIG_ARM_ERRATA_742231 + teq r6, #0x20 @ present in r2p0 + teqne r6, #0x21 @ present in r2p1 + teqne r6, #0x22 @ present in r2p2 + mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register + orreq r10, r10, #1 << 12 @ set bit #12 + orreq r10, r10, #1 << 22 @ set bit #22 + mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register +#endif +#ifdef CONFIG_ARM_ERRATA_743622 + teq r6, #0x20 @ present in r2p0 + teqne r6, #0x21 @ present in r2p1 + teqne r6, #0x22 @ present in r2p2 + mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register + orreq r10, r10, #1 << 6 @ set bit #6 + mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register +#endif + +3: mov r10, #0 #ifdef HARVARD_CACHE mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate #endif @@ -323,6 +358,29 @@ cpu_elf_name: .section ".proc.info.init", #alloc, #execinstr + .type __v7_ca9mp_proc_info, #object +__v7_ca9mp_proc_info: + .long 0x410fc090 @ Required ID value + .long 0xff0ffff0 @ Mask for ID + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ | \ + PMD_FLAGS + .long PMD_TYPE_SECT | \ + PMD_SECT_XN | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + b __v7_ca9mp_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS + .long cpu_v7_name + .long v7_processor_functions + .long v7wbi_tlb_fns + .long v6_user_fns + .long v7_cache_fns + .size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info + /* * Match any ARMv7 processor core. */ diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index 0691176..72e09eb 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -102,6 +102,7 @@ static int op_create_counter(int cpu, int event) if (IS_ERR(pevent)) { ret = PTR_ERR(pevent); } else if (pevent->state != PERF_EVENT_STATE_ACTIVE) { + perf_event_release_kernel(pevent); pr_warning("oprofile: failed to enable event %d " "on CPU %d\n", event, cpu); ret = -EBUSY; @@ -365,6 +366,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) ret = init_driverfs(); if (ret) { kfree(counter_config); + counter_config = NULL; return ret; } @@ -402,7 +404,6 @@ void oprofile_arch_exit(void) struct perf_event *event; if (*perf_events) { - exit_driverfs(); for_each_possible_cpu(cpu) { for (id = 0; id < perf_num_counters; ++id) { event = perf_events[cpu][id]; @@ -413,8 +414,10 @@ void oprofile_arch_exit(void) } } - if (counter_config) + if (counter_config) { kfree(counter_config); + exit_driverfs(); + } } #else int __init oprofile_arch_init(struct oprofile_operations *ops) diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index ea3ca86..aedf9c1 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-nomadik/timer.c + * linux/arch/arm/plat-nomadik/timer.c * * Copyright (C) 2008 STMicroelectronics * Copyright (C) 2010 Alessandro Rubini @@ -75,7 +75,7 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, cr = readl(mtu_base + MTU_CR(1)); writel(0, mtu_base + MTU_LR(1)); writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1)); - writel(0x2, mtu_base + MTU_IMSC); + writel(1 << 1, mtu_base + MTU_IMSC); break; case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: @@ -131,25 +131,23 @@ void __init nmdk_timer_init(void) { unsigned long rate; struct clk *clk0; - struct clk *clk1; - u32 cr; + u32 cr = MTU_CRn_32BITS; clk0 = clk_get_sys("mtu0", NULL); BUG_ON(IS_ERR(clk0)); - clk1 = clk_get_sys("mtu1", NULL); - BUG_ON(IS_ERR(clk1)); - clk_enable(clk0); - clk_enable(clk1); /* - * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: - * use a divide-by-16 counter if it's more than 16MHz + * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz + * for ux500. + * Use a divide-by-16 counter if the tick rate is more than 32MHz. + * At 32 MHz, the timer (with 32 bit counter) can be programmed + * to wake-up at a max 127s a head in time. Dividing a 2.4 MHz timer + * with 16 gives too low timer resolution. */ - cr = MTU_CRn_32BITS;; rate = clk_get_rate(clk0); - if (rate > 16 << 20) { + if (rate > 32000000) { rate /= 16; cr |= MTU_CRn_PRESCALE_16; } else { @@ -170,15 +168,8 @@ void __init nmdk_timer_init(void) pr_err("timer: failed to initialize clock source %s\n", nmdk_clksrc.name); - /* Timer 1 is used for events, fix according to rate */ - cr = MTU_CRn_32BITS; - rate = clk_get_rate(clk1); - if (rate > 16 << 20) { - rate /= 16; - cr |= MTU_CRn_PRESCALE_16; - } else { - cr |= MTU_CRn_PRESCALE_1; - } + /* Timer 1 is used for events */ + clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index e39a417..a92cb49 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -33,7 +33,7 @@ config OMAP_DEBUG_DEVICES config OMAP_DEBUG_LEDS bool depends on OMAP_DEBUG_DEVICES - default y if LEDS + default y if LEDS_CLASS config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index a202a2c..6cd151b 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -320,6 +320,7 @@ void flush_iotlb_page(struct iommu *obj, u32 da) if ((start <= da) && (da < start + bytes)) { dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n", __func__, start, da, bytes); + iotlb_load_cr(obj, &cr); iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); } } diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index e31496e..0c8612f 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -156,7 +156,7 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) /* Writing zero to RSYNC_ERR clears the IRQ */ MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1)); } else { - complete(&mcbsp_rx->tx_irq_completion); + complete(&mcbsp_rx->rx_irq_completion); } return IRQ_HANDLED; diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 226b2e8..10b3b4c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -220,20 +220,7 @@ void __init omap_map_sram(void) if (omap_sram_size == 0) return; - if (cpu_is_omap24xx()) { - omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; - - base = OMAP2_SRAM_PA; - base = ROUND_DOWN(base, PAGE_SIZE); - omap_sram_io_desc[0].pfn = __phys_to_pfn(base); - } - if (cpu_is_omap34xx()) { - omap_sram_io_desc[0].virtual = OMAP3_SRAM_VA; - base = OMAP3_SRAM_PA; - base = ROUND_DOWN(base, PAGE_SIZE); - omap_sram_io_desc[0].pfn = __phys_to_pfn(base); - /* * SRAM must be marked as non-cached on OMAP3 since the * CORE DPLL M2 divider change code (in SRAM) runs with the @@ -244,13 +231,11 @@ void __init omap_map_sram(void) omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED; } - if (cpu_is_omap44xx()) { - omap_sram_io_desc[0].virtual = OMAP4_SRAM_VA; - base = OMAP4_SRAM_PA; - base = ROUND_DOWN(base, PAGE_SIZE); - omap_sram_io_desc[0].pfn = __phys_to_pfn(base); - } - omap_sram_io_desc[0].length = 1024 * 1024; /* Use section desc */ + omap_sram_io_desc[0].virtual = omap_sram_base; + base = omap_sram_start; + base = ROUND_DOWN(base, PAGE_SIZE); + omap_sram_io_desc[0].pfn = __phys_to_pfn(base); + omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE); iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", diff --git a/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h index 7b4eadc..abcc36e 100644 --- a/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h +++ b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h @@ -25,6 +25,13 @@ * * 4. matrix key and direct key will use the same debounce_interval by * default, which should be sufficient in most cases + * + * pxa168 keypad platform specific parameter + * + * NOTE: + * clear_wakeup_event callback is a workaround required to clear the + * keypad interrupt. The keypad wake must be cleared in addition to + * reading the MI/DI bits in the KPC register. */ struct pxa27x_keypad_platform_data { @@ -52,6 +59,9 @@ struct pxa27x_keypad_platform_data { /* key debounce interval */ unsigned int debounce_interval; + + /* clear wakeup event requirement for pxa168 */ + void (*clear_wakeup_event)(void); }; extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info); diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index c6a855d..2596096 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -7,7 +7,7 @@ config PLAT_S5P bool - depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310) + depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310) default y select ARM_VIC if !ARCH_S5PV310 select ARM_GIC if ARCH_S5PV310 @@ -30,7 +30,7 @@ config S5P_EXT_INT bool help Use the external interrupts (other than GPIO interrupts.) - Note: Do not choose this for S5P6440. + Note: Do not choose this for S5P6440 and S5P6450. config S5P_DEV_FIMC0 bool @@ -46,3 +46,8 @@ config S5P_DEV_FIMC2 bool help Compile in platform device definitions for FIMC controller 2 + +config S5P_DEV_ONENAND + bool + help + Compile in platform device definition for OneNAND controller diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index b2e0296..f3e917e 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o +obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index b5e2552..8aaf4e6 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -74,6 +74,13 @@ struct clk clk_fout_epll = { .ctrlbit = (1 << 31), }; +/* DPLL clock output */ +struct clk clk_fout_dpll = { + .name = "fout_dpll", + .id = -1, + .ctrlbit = (1 << 31), +}; + /* VPLL clock output */ struct clk clk_fout_vpll = { .name = "fout_vpll", @@ -122,6 +129,17 @@ struct clksrc_sources clk_src_epll = { .nr_sources = ARRAY_SIZE(clk_src_epll_list), }; +/* Possible clock sources for DPLL Mux */ +static struct clk *clk_src_dpll_list[] = { + [0] = &clk_fin_dpll, + [1] = &clk_fout_dpll, +}; + +struct clksrc_sources clk_src_dpll = { + .sources = clk_src_dpll_list, + .nr_sources = ARRAY_SIZE(clk_src_dpll_list), +}; + struct clk clk_vpll = { .name = "vpll", .id = -1, @@ -145,6 +163,7 @@ static struct clk *s5p_clks[] __initdata = { &clk_fout_apll, &clk_fout_mpll, &clk_fout_epll, + &clk_fout_dpll, &clk_fout_vpll, &clk_arm, &clk_vpll, diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c index b07a078..74f7f5a 100644 --- a/arch/arm/plat-s5p/cpu.c +++ b/arch/arm/plat-s5p/cpu.c @@ -19,6 +19,7 @@ #include <plat/cpu.h> #include <plat/s5p6440.h> #include <plat/s5p6442.h> +#include <plat/s5p6450.h> #include <plat/s5pc100.h> #include <plat/s5pv210.h> #include <plat/s5pv310.h> @@ -27,6 +28,7 @@ static const char name_s5p6440[] = "S5P6440"; static const char name_s5p6442[] = "S5P6442"; +static const char name_s5p6450[] = "S5P6450"; static const char name_s5pc100[] = "S5PC100"; static const char name_s5pv210[] = "S5PV210/S5PC110"; static const char name_s5pv310[] = "S5PV310"; @@ -38,7 +40,7 @@ static struct cpu_table cpu_ids[] __initdata = { .map_io = s5p6440_map_io, .init_clocks = s5p6440_init_clocks, .init_uarts = s5p6440_init_uarts, - .init = s5p6440_init, + .init = s5p64x0_init, .name = name_s5p6440, }, { .idcode = 0x36442000, @@ -49,6 +51,14 @@ static struct cpu_table cpu_ids[] __initdata = { .init = s5p6442_init, .name = name_s5p6442, }, { + .idcode = 0x36450000, + .idmask = 0xffffff00, + .map_io = s5p6450_map_io, + .init_clocks = s5p6450_init_clocks, + .init_uarts = s5p6450_init_uarts, + .init = s5p64x0_init, + .name = name_s5p6450, + }, { .idcode = 0x43100000, .idmask = 0xfffff000, .map_io = s5pc100_map_io, @@ -89,33 +99,11 @@ static struct map_desc s5p_iodesc[] __initdata = { .length = SZ_64K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S3C_VA_UART, - .pfn = __phys_to_pfn(S3C_PA_UART), - .length = SZ_512K, - .type = MT_DEVICE, -#ifdef CONFIG_ARM_VIC - }, { - .virtual = (unsigned long)VA_VIC0, - .pfn = __phys_to_pfn(S5P_PA_VIC0), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = (unsigned long)VA_VIC1, - .pfn = __phys_to_pfn(S5P_PA_VIC1), - .length = SZ_16K, - .type = MT_DEVICE, -#endif - }, { .virtual = (unsigned long)S3C_VA_TIMER, .pfn = __phys_to_pfn(S5P_PA_TIMER), .length = SZ_16K, .type = MT_DEVICE, }, { - .virtual = (unsigned long)S5P_VA_GPIO, - .pfn = __phys_to_pfn(S5P_PA_GPIO), - .length = SZ_4K, - .type = MT_DEVICE, - }, { .virtual = (unsigned long)S3C_VA_WATCHDOG, .pfn = __phys_to_pfn(S3C_PA_WDT), .length = SZ_4K, diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-fimc0.c index d3f1a9b..608770f 100644 --- a/arch/arm/plat-s5p/dev-fimc0.c +++ b/arch/arm/plat-s5p/dev-fimc0.c @@ -10,6 +10,7 @@ */ #include <linux/kernel.h> +#include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/ioport.h> @@ -18,7 +19,7 @@ static struct resource s5p_fimc0_resource[] = { [0] = { .start = S5P_PA_FIMC0, - .end = S5P_PA_FIMC0 + SZ_1M - 1, + .end = S5P_PA_FIMC0 + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -28,9 +29,15 @@ static struct resource s5p_fimc0_resource[] = { }, }; +static u64 s5p_fimc0_dma_mask = DMA_BIT_MASK(32); + struct platform_device s5p_device_fimc0 = { .name = "s5p-fimc", .id = 0, .num_resources = ARRAY_SIZE(s5p_fimc0_resource), .resource = s5p_fimc0_resource, + .dev = { + .dma_mask = &s5p_fimc0_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-fimc1.c index 41bd698..76e3a97 100644 --- a/arch/arm/plat-s5p/dev-fimc1.c +++ b/arch/arm/plat-s5p/dev-fimc1.c @@ -10,6 +10,7 @@ */ #include <linux/kernel.h> +#include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/ioport.h> @@ -18,7 +19,7 @@ static struct resource s5p_fimc1_resource[] = { [0] = { .start = S5P_PA_FIMC1, - .end = S5P_PA_FIMC1 + SZ_1M - 1, + .end = S5P_PA_FIMC1 + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -28,9 +29,15 @@ static struct resource s5p_fimc1_resource[] = { }, }; +static u64 s5p_fimc1_dma_mask = DMA_BIT_MASK(32); + struct platform_device s5p_device_fimc1 = { .name = "s5p-fimc", .id = 1, .num_resources = ARRAY_SIZE(s5p_fimc1_resource), .resource = s5p_fimc1_resource, + .dev = { + .dma_mask = &s5p_fimc1_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-fimc2.c index dfddeda..24d2981 100644 --- a/arch/arm/plat-s5p/dev-fimc2.c +++ b/arch/arm/plat-s5p/dev-fimc2.c @@ -10,6 +10,7 @@ */ #include <linux/kernel.h> +#include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/ioport.h> @@ -18,7 +19,7 @@ static struct resource s5p_fimc2_resource[] = { [0] = { .start = S5P_PA_FIMC2, - .end = S5P_PA_FIMC2 + SZ_1M - 1, + .end = S5P_PA_FIMC2 + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -28,9 +29,15 @@ static struct resource s5p_fimc2_resource[] = { }, }; +static u64 s5p_fimc2_dma_mask = DMA_BIT_MASK(32); + struct platform_device s5p_device_fimc2 = { .name = "s5p-fimc", .id = 2, .num_resources = ARRAY_SIZE(s5p_fimc2_resource), .resource = s5p_fimc2_resource, + .dev = { + .dma_mask = &s5p_fimc2_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, }; diff --git a/arch/arm/mach-s5pv210/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c index f8ede33..6db9262 100644 --- a/arch/arm/mach-s5pv210/dev-onenand.c +++ b/arch/arm/plat-s5p/dev-onenand.c @@ -1,10 +1,12 @@ -/* - * linux/arch/arm/mach-s5pv210/dev-onenand.c +/* linux/arch/arm/plat-s5p/dev-onenand.c + * + * Copyright 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Copyright (c) 2008-2010 Samsung Electronics * Kyungmin Park <kyungmin.park@samsung.com> * - * S5PC110 series device definition for OneNAND devices + * S5P series device definition for OneNAND devices * * 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 @@ -19,15 +21,15 @@ #include <mach/irqs.h> #include <mach/map.h> -static struct resource s5pc110_onenand_resources[] = { +static struct resource s5p_onenand_resources[] = { [0] = { - .start = S5PC110_PA_ONENAND, - .end = S5PC110_PA_ONENAND + SZ_128K - 1, + .start = S5P_PA_ONENAND, + .end = S5P_PA_ONENAND + SZ_128K - 1, .flags = IORESOURCE_MEM, }, [1] = { - .start = S5PC110_PA_ONENAND_DMA, - .end = S5PC110_PA_ONENAND_DMA + SZ_8K - 1, + .start = S5P_PA_ONENAND_DMA, + .end = S5P_PA_ONENAND_DMA + SZ_8K - 1, .flags = IORESOURCE_MEM, }, [2] = { @@ -37,19 +39,19 @@ static struct resource s5pc110_onenand_resources[] = { }, }; -struct platform_device s5pc110_device_onenand = { +struct platform_device s5p_device_onenand = { .name = "s5pc110-onenand", .id = -1, - .num_resources = ARRAY_SIZE(s5pc110_onenand_resources), - .resource = s5pc110_onenand_resources, + .num_resources = ARRAY_SIZE(s5p_onenand_resources), + .resource = s5p_onenand_resources, }; -void s5pc110_onenand_set_platdata(struct onenand_platform_data *pdata) +void s5p_onenand_set_platdata(struct onenand_platform_data *pdata) { struct onenand_platform_data *pd; pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL); if (!pd) printk(KERN_ERR "%s: no memory for platform data\n", __func__); - s5pc110_device_onenand.dev.platform_data = pd; + s5p_device_onenand.dev.platform_data = pd; } diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c index a89331e..6a73428 100644 --- a/arch/arm/plat-s5p/dev-uart.c +++ b/arch/arm/plat-s5p/dev-uart.c @@ -119,6 +119,56 @@ static struct resource s5p_uart3_resource[] = { #endif }; +static struct resource s5p_uart4_resource[] = { +#if CONFIG_SERIAL_SAMSUNG_UARTS > 4 + [0] = { + .start = S5P_PA_UART4, + .end = S5P_PA_UART4 + S5P_SZ_UART, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S5P_UART_RX4, + .end = IRQ_S5P_UART_RX4, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S5P_UART_TX4, + .end = IRQ_S5P_UART_TX4, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_S5P_UART_ERR4, + .end = IRQ_S5P_UART_ERR4, + .flags = IORESOURCE_IRQ, + }, +#endif +}; + +static struct resource s5p_uart5_resource[] = { +#if CONFIG_SERIAL_SAMSUNG_UARTS > 5 + [0] = { + .start = S5P_PA_UART5, + .end = S5P_PA_UART5 + S5P_SZ_UART, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S5P_UART_RX5, + .end = IRQ_S5P_UART_RX5, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S5P_UART_TX5, + .end = IRQ_S5P_UART_TX5, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_S5P_UART_ERR5, + .end = IRQ_S5P_UART_ERR5, + .flags = IORESOURCE_IRQ, + }, +#endif +}; + struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = { [0] = { .resources = s5p_uart0_resource, @@ -136,4 +186,12 @@ struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = { .resources = s5p_uart3_resource, .nr_resources = ARRAY_SIZE(s5p_uart3_resource), }, + [4] = { + .resources = s5p_uart4_resource, + .nr_resources = ARRAY_SIZE(s5p_uart4_resource), + }, + [5] = { + .resources = s5p_uart5_resource, + .nr_resources = ARRAY_SIZE(s5p_uart5_resource), + }, }; diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h index 4e8fe08..bf28fad 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h @@ -47,6 +47,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con, } #define PLL46XX_KDIV_MASK (0xFFFF) +#define PLL4650C_KDIV_MASK (0xFFF) #define PLL46XX_MDIV_MASK (0x1FF) #define PLL46XX_PDIV_MASK (0x3F) #define PLL46XX_SDIV_MASK (0x7) @@ -57,6 +58,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con, enum pll46xx_type_t { pll_4600, pll_4650, + pll_4650c, }; static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, @@ -72,6 +74,11 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; kdiv = pll_con1 & PLL46XX_KDIV_MASK; + if (pll_type == pll_4650c) + kdiv = pll_con1 & PLL4650C_KDIV_MASK; + else + kdiv = pll_con1 & PLL46XX_KDIV_MASK; + tmp = baseclk; if (pll_type == pll_4600) { diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h index 09418b1..17036c8 100644 --- a/arch/arm/plat-s5p/include/plat/s5p-clock.h +++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h @@ -1,7 +1,7 @@ /* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h * - * Copyright 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com * * Header file for s5p clock support * @@ -20,6 +20,7 @@ #define clk_fin_apll clk_ext_xtal_mux #define clk_fin_mpll clk_ext_xtal_mux #define clk_fin_epll clk_ext_xtal_mux +#define clk_fin_dpll clk_ext_xtal_mux #define clk_fin_vpll clk_ext_xtal_mux #define clk_fin_hpll clk_ext_xtal_mux @@ -30,6 +31,7 @@ extern struct clk s5p_clk_27m; extern struct clk clk_fout_apll; extern struct clk clk_fout_mpll; extern struct clk clk_fout_epll; +extern struct clk clk_fout_dpll; extern struct clk clk_fout_vpll; extern struct clk clk_arm; extern struct clk clk_vpll; @@ -37,8 +39,8 @@ extern struct clk clk_vpll; extern struct clksrc_sources clk_src_apll; extern struct clksrc_sources clk_src_mpll; extern struct clksrc_sources clk_src_epll; +extern struct clksrc_sources clk_src_dpll; -extern int s5p6440_clk48m_ctrl(struct clk *clk, int enable); extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable); #endif /* __ASM_PLAT_S5P_CLOCK_H */ diff --git a/arch/arm/plat-s5p/include/plat/s5p6440.h b/arch/arm/plat-s5p/include/plat/s5p6440.h index a4cd75a..528585d 100644 --- a/arch/arm/plat-s5p/include/plat/s5p6440.h +++ b/arch/arm/plat-s5p/include/plat/s5p6440.h @@ -12,24 +12,23 @@ /* Common init code for S5P6440 related SoCs */ -extern void s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); extern void s5p6440_register_clocks(void); extern void s5p6440_setup_clocks(void); #ifdef CONFIG_CPU_S5P6440 -extern int s5p6440_init(void); +extern int s5p64x0_init(void); extern void s5p6440_init_irq(void); extern void s5p6440_map_io(void); extern void s5p6440_init_clocks(int xtal); -#define s5p6440_init_uarts s5p6440_common_init_uarts +extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no); #else #define s5p6440_init_clocks NULL #define s5p6440_init_uarts NULL #define s5p6440_map_io NULL -#define s5p6440_init NULL +#define s5p64x0_init NULL #endif /* S5P6440 timer */ diff --git a/arch/arm/plat-s5p/include/plat/s5p6450.h b/arch/arm/plat-s5p/include/plat/s5p6450.h new file mode 100644 index 0000000..640a41c --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/s5p6450.h @@ -0,0 +1,36 @@ +/* arch/arm/plat-s5p/include/plat/s5p6450.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Header file for s5p6450 cpu support + * + * 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. +*/ + +/* Common init code for S5P6450 related SoCs */ + +extern void s5p6450_register_clocks(void); +extern void s5p6450_setup_clocks(void); + +#ifdef CONFIG_CPU_S5P6450 + +extern int s5p64x0_init(void); +extern void s5p6450_init_irq(void); +extern void s5p6450_map_io(void); +extern void s5p6450_init_clocks(int xtal); + +extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +#else +#define s5p6450_init_clocks NULL +#define s5p6450_init_uarts NULL +#define s5p6450_map_io NULL +#define s5p64x0_init NULL +#endif + +/* S5P6450 timer */ + +extern struct sys_timer s5p6450_timer; diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index 04d9521..e8f2be2 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -435,7 +435,6 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state) static int s3c_adc_resume(struct platform_device *pdev) { struct adc_device *adc = platform_get_drvdata(pdev); - unsigned long flags; clk_enable(adc->clk); enable_irq(adc->irq); diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c index 90a2051..e8d20b0 100644 --- a/arch/arm/plat-samsung/clock.c +++ b/arch/arm/plat-samsung/clock.c @@ -48,6 +48,9 @@ #include <plat/clock.h> #include <plat/cpu.h> +#include <linux/serial_core.h> +#include <plat/regs-serial.h> /* for s3c24xx_uart_devs */ + /* clock information */ static LIST_HEAD(clocks); @@ -65,6 +68,28 @@ static int clk_null_enable(struct clk *clk, int enable) return 0; } +static int dev_is_s3c_uart(struct device *dev) +{ + struct platform_device **pdev = s3c24xx_uart_devs; + int i; + for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++) + if (*pdev && dev == &(*pdev)->dev) + return 1; + return 0; +} + +/* + * Serial drivers call get_clock() very early, before platform bus + * has been set up, this requires a special check to let them get + * a proper clock + */ + +static int dev_is_platform_device(struct device *dev) +{ + return dev->bus == &platform_bus_type || + (dev->bus == NULL && dev_is_s3c_uart(dev)); +} + /* Clock API calls */ struct clk *clk_get(struct device *dev, const char *id) @@ -73,7 +98,7 @@ struct clk *clk_get(struct device *dev, const char *id) struct clk *clk = ERR_PTR(-ENOENT); int idno; - if (dev == NULL || dev->bus != &platform_bus_type) + if (dev == NULL || !dev_is_platform_device(dev)) idno = -1; else idno = to_platform_device(dev)->id; diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 57b68a5..e3d41ea 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -273,13 +273,13 @@ s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) if (!chip) return -EINVAL; - off = chip->chip.base - pin; + off = pin - chip->chip.base; shift = off * 2; reg = chip->base + 0x0C; drvstr = __raw_readl(reg); - drvstr = 0xffff & (0x3 << shift); drvstr = drvstr >> shift; + drvstr &= 0x3; return (__force s5p_gpio_drvstr_t)drvstr; } @@ -296,11 +296,12 @@ int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) if (!chip) return -EINVAL; - off = chip->chip.base - pin; + off = pin - chip->chip.base; shift = off * 2; reg = chip->base + 0x0C; tmp = __raw_readl(reg); + tmp &= ~(0x3 << shift); tmp |= drvstr << shift; __raw_writel(tmp, reg); diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 6412933..9addb3d 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -79,7 +79,7 @@ extern struct sysdev_class s3c2442_sysclass; extern struct sysdev_class s3c2443_sysclass; extern struct sysdev_class s3c6410_sysclass; extern struct sysdev_class s3c64xx_sysclass; -extern struct sysdev_class s5p6440_sysclass; +extern struct sysdev_class s5p64x0_sysclass; extern struct sysdev_class s5p6442_sysclass; extern struct sysdev_class s5pv210_sysclass; diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 85f6f23..7d448e1 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -67,13 +67,15 @@ extern struct platform_device s5pv210_device_spi0; extern struct platform_device s5pv210_device_spi1; extern struct platform_device s5p6440_device_spi0; extern struct platform_device s5p6440_device_spi1; +extern struct platform_device s5p6450_device_spi0; +extern struct platform_device s5p6450_device_spi1; extern struct platform_device s3c_device_hwmon; extern struct platform_device s3c_device_nand; extern struct platform_device s3c_device_onenand; extern struct platform_device s3c64xx_device_onenand1; -extern struct platform_device s5pc110_device_onenand; +extern struct platform_device s5p_device_onenand; extern struct platform_device s3c_device_usbgadget; extern struct platform_device s3c_device_usb_hsotg; @@ -95,6 +97,9 @@ extern struct platform_device s5p6442_device_spi; extern struct platform_device s5p6440_device_pcm; extern struct platform_device s5p6440_device_iis; +extern struct platform_device s5p6450_device_iis0; +extern struct platform_device s5p6450_device_pcm0; + extern struct platform_device s5pc100_device_ac97; extern struct platform_device s5pc100_device_pcm0; extern struct platform_device s5pc100_device_pcm1; diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index db4112c..1c6b929 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -143,12 +143,12 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); /* Define values for the drvstr available for each gpio pin. * * These values control the value of the output signal driver strength, - * configurable on most pins on the S5C series. + * configurable on most pins on the S5P series. */ -#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x00) -#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x01) -#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x10) -#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x11) +#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x0) +#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x2) +#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x1) +#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x3) /** * s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h index 5fe6721..8107442 100644 --- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h @@ -32,6 +32,12 @@ enum dma_ch { DMACH_UART2_TX, DMACH_UART3_RX, DMACH_UART3_TX, + DMACH_UART4_RX, + DMACH_UART4_TX, + DMACH_UART5_RX, + DMACH_UART5_TX, + DMACH_USI_RX, + DMACH_USI_TX, DMACH_IRDA, DMACH_I2S0_RX, DMACH_I2S0_TX, @@ -64,6 +70,20 @@ enum dma_ch { DMACH_MSM_REQ2, DMACH_MSM_REQ1, DMACH_MSM_REQ0, + DMACH_SLIMBUS0_RX, + DMACH_SLIMBUS0_TX, + DMACH_SLIMBUS0AUX_RX, + DMACH_SLIMBUS0AUX_TX, + DMACH_SLIMBUS1_RX, + DMACH_SLIMBUS1_TX, + DMACH_SLIMBUS2_RX, + DMACH_SLIMBUS2_TX, + DMACH_SLIMBUS3_RX, + DMACH_SLIMBUS3_TX, + DMACH_SLIMBUS4_RX, + DMACH_SLIMBUS4_TX, + DMACH_SLIMBUS5_RX, + DMACH_SLIMBUS5_TX, /* END Marker, also used to denote a reserved channel */ DMACH_MAX, }; diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index e5aba8f..ae8e802 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -65,7 +65,7 @@ struct s3c64xx_spi_info { extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); -extern void s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); +extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); extern void s5p6442_spi_set_info(int cntrlr, int src_clk_nr, int num_cs); #endif /* __S3C64XX_PLAT_SPI_H */ diff --git a/arch/arm/plat-tcc/Kconfig b/arch/arm/plat-tcc/Kconfig new file mode 100644 index 0000000..1bf4995 --- /dev/null +++ b/arch/arm/plat-tcc/Kconfig @@ -0,0 +1,20 @@ +if ARCH_TCC_926 + +menu "Telechips ARM926-based CPUs" + +choice + prompt "Telechips CPU type:" + default ARCH_TCC8K + +config ARCH_TCC8K + bool TCC8000 + select USB_ARCH_HAS_OHCI + help + Support for Telechips TCC8000 systems + +endchoice + +source "arch/arm/mach-tcc8k/Kconfig" + +endmenu +endif diff --git a/arch/arm/plat-tcc/Makefile b/arch/arm/plat-tcc/Makefile new file mode 100644 index 0000000..eceabc8 --- /dev/null +++ b/arch/arm/plat-tcc/Makefile @@ -0,0 +1,3 @@ +# "Telechips Platform Common Modules" + +obj-y := clock.o system.o diff --git a/arch/arm/plat-tcc/clock.c b/arch/arm/plat-tcc/clock.c new file mode 100644 index 0000000..f3ced10 --- /dev/null +++ b/arch/arm/plat-tcc/clock.c @@ -0,0 +1,179 @@ +/* + * Clock framework for Telechips SoCs + * Based on arch/arm/plat-mxc/clock.c + * + * Copyright (C) 2004 - 2005 Nokia corporation + * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> + * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> + * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2010 Hans J. Koch, hjk@linutronix.de + * + * Licensed under the terms of the GPL v2. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/string.h> + +#include <mach/clock.h> +#include <mach/hardware.h> + +static DEFINE_MUTEX(clocks_mutex); + +/*------------------------------------------------------------------------- + * Standard clock functions defined in include/linux/clk.h + *-------------------------------------------------------------------------*/ + +static void __clk_disable(struct clk *clk) +{ + BUG_ON(clk->refcount == 0); + + if (!(--clk->refcount) && clk->disable) { + /* Unconditionally disable the clock in hardware */ + clk->disable(clk); + /* recursively disable parents */ + if (clk->parent) + __clk_disable(clk->parent); + } +} + +static int __clk_enable(struct clk *clk) +{ + int ret = 0; + + if (clk->refcount++ == 0 && clk->enable) { + if (clk->parent) + ret = __clk_enable(clk->parent); + if (ret) + return ret; + else + return clk->enable(clk); + } + + return 0; +} + +/* This function increments the reference count on the clock and enables the + * clock if not already enabled. The parent clock tree is recursively enabled + */ +int clk_enable(struct clk *clk) +{ + int ret = 0; + + if (!clk) + return -EINVAL; + + mutex_lock(&clocks_mutex); + ret = __clk_enable(clk); + mutex_unlock(&clocks_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_enable); + +/* This function decrements the reference count on the clock and disables + * the clock when reference count is 0. The parent clock tree is + * recursively disabled + */ +void clk_disable(struct clk *clk) +{ + if (!clk) + return; + + mutex_lock(&clocks_mutex); + __clk_disable(clk); + mutex_unlock(&clocks_mutex); +} +EXPORT_SYMBOL_GPL(clk_disable); + +/* Retrieve the *current* clock rate. If the clock itself + * does not provide a special calculation routine, ask + * its parent and so on, until one is able to return + * a valid clock rate + */ +unsigned long clk_get_rate(struct clk *clk) +{ + if (!clk) + return 0UL; + + if (clk->get_rate) + return clk->get_rate(clk); + + return clk_get_rate(clk->parent); +} +EXPORT_SYMBOL_GPL(clk_get_rate); + +/* Round the requested clock rate to the nearest supported + * rate that is less than or equal to the requested rate. + * This is dependent on the clock's current parent. + */ +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (!clk) + return 0; + if (!clk->round_rate) + return 0; + + return clk->round_rate(clk, rate); +} +EXPORT_SYMBOL_GPL(clk_round_rate); + +/* Set the clock to the requested clock rate. The rate must + * match a supported rate exactly based on what clk_round_rate returns + */ +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EINVAL; + + if (!clk) + return ret; + if (!clk->set_rate || !rate) + return ret; + + mutex_lock(&clocks_mutex); + ret = clk->set_rate(clk, rate); + mutex_unlock(&clocks_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_rate); + +/* Set the clock's parent to another clock source */ +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *old; + int ret = -EINVAL; + + if (!clk) + return ret; + if (!clk->set_parent || !parent) + return ret; + + mutex_lock(&clocks_mutex); + old = clk->parent; + if (clk->refcount) + __clk_enable(parent); + ret = clk->set_parent(clk, parent); + if (ret) + old = parent; + if (clk->refcount) + __clk_disable(old); + mutex_unlock(&clocks_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_parent); + +/* Retrieve the clock's parent clock source */ +struct clk *clk_get_parent(struct clk *clk) +{ + if (!clk) + return NULL; + + return clk->parent; +} +EXPORT_SYMBOL_GPL(clk_get_parent); diff --git a/arch/arm/plat-tcc/include/mach/clkdev.h b/arch/arm/plat-tcc/include/mach/clkdev.h new file mode 100644 index 0000000..04b37a8 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/plat-tcc/include/mach/clock.h b/arch/arm/plat-tcc/include/mach/clock.h new file mode 100644 index 0000000..a12f58a --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/clock.h @@ -0,0 +1,48 @@ +/* + * Low level clock header file for Telechips TCC architecture + * (C) 2010 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the GPL v2. + */ + +#ifndef __ASM_ARCH_TCC_CLOCK_H__ +#define __ASM_ARCH_TCC_CLOCK_H__ + +#ifndef __ASSEMBLY__ + +struct clk { + struct clk *parent; + /* id number of a root clock, 0 for normal clocks */ + int root_id; + /* Reference count of clock enable/disable */ + int refcount; + /* Address of associated BCLKCTRx register. Must be set. */ + void __iomem *bclkctr; + /* Bit position for BCLKCTRx. Must be set. */ + int bclk_shift; + /* Address of ACLKxxx register, if any. */ + void __iomem *aclkreg; + /* get the current clock rate (always a fresh value) */ + unsigned long (*get_rate) (struct clk *); + /* Function ptr to set the clock to a new rate. The rate must match a + supported rate returned from round_rate. Leave blank if clock is not + programmable */ + int (*set_rate) (struct clk *, unsigned long); + /* Function ptr to round the requested clock rate to the nearest + supported rate that is less than or equal to the requested rate. */ + unsigned long (*round_rate) (struct clk *, unsigned long); + /* Function ptr to enable the clock. Leave blank if clock can not + be gated. */ + int (*enable) (struct clk *); + /* Function ptr to disable the clock. Leave blank if clock can not + be gated. */ + void (*disable) (struct clk *); + /* Function ptr to set the parent clock of the clock. */ + int (*set_parent) (struct clk *, struct clk *); +}; + +int clk_register(struct clk *clk); +void clk_unregister(struct clk *clk); + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_ARCH_MXC_CLOCK_H__ */ diff --git a/arch/arm/plat-tcc/include/mach/debug-macro.S b/arch/arm/plat-tcc/include/mach/debug-macro.S new file mode 100644 index 0000000..9753784 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/debug-macro.S @@ -0,0 +1,33 @@ +/* + * Copyright (C) 1994-1999 Russell King + * Copyright (C) 2008-2009 Telechips + * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * 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. + * + */ + + .macro addruart,rx,tmp + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x90000000 @ physical base address + movne \rx, #0xF1000000 @ virtual base + orr \rx, \rx, #0x00007000 @ UART0 + .endm + + .macro senduart,rd,rx + strb \rd, [\rx, #0x44] + .endm + + .macro waituart,rd,rx + .endm + + .macro busyuart,rd,rx +1001: + ldr \rd, [\rx, #0x14] + tst \rd, #0x20 + + beq 1001b + .endm diff --git a/arch/arm/plat-tcc/include/mach/entry-macro.S b/arch/arm/plat-tcc/include/mach/entry-macro.S new file mode 100644 index 0000000..748f401 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/entry-macro.S @@ -0,0 +1,68 @@ +/* + * include/asm-arm/arch-tcc83x/entry-macro.S + * + * Author : <linux@telechips.com> + * Created: June 10, 2008 + * Description: Low-level IRQ helper macros for Telechips-based platforms + * + * Copyright (C) 2008-2009 Telechips + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <mach/hardware.h> +#include <mach/irqs.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \base, =0xF2003000 @ base address of PIC registers + + @@ read MREQ register of PIC0 + + mov \irqnr, #0 + ldr \irqstat, [\base, #0x00000014 ] @ lower 32 interrupts + cmp \irqstat, #0 + bne 1001f + + @@ read MREQ register of PIC1 + + ldr \irqstat, [\base, #0x00000094] @ upper 32 interrupts + cmp \irqstat, #0 + beq 1002f + mov \irqnr, #0x20 + +1001: + movs \tmp, \irqstat, lsl #16 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #16 + + movs \tmp, \irqstat, lsl #8 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #8 + + movs \tmp, \irqstat, lsl #4 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #4 + + movs \tmp, \irqstat, lsl #2 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #2 + + movs \tmp, \irqstat, lsl #1 + addeq \irqnr, \irqnr, #1 + orrs \base, \base, #1 +1002: + @@ exit here, Z flag unset if IRQ + + .endm diff --git a/arch/arm/plat-tcc/include/mach/hardware.h b/arch/arm/plat-tcc/include/mach/hardware.h new file mode 100644 index 0000000..e70d126 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/hardware.h @@ -0,0 +1,43 @@ +/* + * Author: RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com> + * Reorganized for Linux-2.6 by Tony Lindgren <tony@atomide.com> + * and Dirk Behme <dirk.behme@de.bosch.com> + * Rewritten by: <linux@telechips.com> + * Description: Hardware definitions for TCC8300 processors and boards + * + * Copyright (C) 2001 RidgeRun, Inc. + * Copyright (C) 2008-2009 Telechips + * + * Modifications for mainline (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GNU Pulic License version 2. + */ + +#ifndef __ASM_ARCH_TCC_HARDWARE_H +#define __ASM_ARCH_TCC_HARDWARE_H + +#include <asm/sizes.h> +#ifndef __ASSEMBLER__ +#include <asm/types.h> +#endif +#include <mach/io.h> + +/* + * ---------------------------------------------------------------------------- + * Clocks + * ---------------------------------------------------------------------------- + */ +#define CLKGEN_REG_BASE 0xfffece00 +#define ARM_CKCTL (CLKGEN_REG_BASE + 0x0) +#define ARM_IDLECT1 (CLKGEN_REG_BASE + 0x4) +#define ARM_IDLECT2 (CLKGEN_REG_BASE + 0x8) +#define ARM_EWUPCT (CLKGEN_REG_BASE + 0xC) +#define ARM_RSTCT1 (CLKGEN_REG_BASE + 0x10) +#define ARM_RSTCT2 (CLKGEN_REG_BASE + 0x14) +#define ARM_SYSST (CLKGEN_REG_BASE + 0x18) +#define ARM_IDLECT3 (CLKGEN_REG_BASE + 0x24) + +/* DPLL control registers */ +#define DPLL_CTL 0xfffecf00 + +#endif /* __ASM_ARCH_TCC_HARDWARE_H */ diff --git a/arch/arm/plat-tcc/include/mach/io.h b/arch/arm/plat-tcc/include/mach/io.h new file mode 100644 index 0000000..3e911d3 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/io.h @@ -0,0 +1,23 @@ +/* + * IO definitions for TCC8000 processors and boards + * + * Copyright (C) 1997-1999 Russell King + * Copyright (C) 2008-2009 Telechips + * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GNU Public License version 2. + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +/* + * We don't actually have real ISA nor PCI buses, but there is so many + * drivers out there that might just work if we fake them... + */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/plat-tcc/include/mach/irqs.h b/arch/arm/plat-tcc/include/mach/irqs.h new file mode 100644 index 0000000..da86389 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/irqs.h @@ -0,0 +1,83 @@ +/* + * IRQ definitions for TCC8xxx + * + * Copyright (C) 2008-2009 Telechips + * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GPL v2. + * + */ + +#ifndef __ASM_ARCH_TCC_IRQS_H +#define __ASM_ARCH_TCC_IRQS_H + +#define NR_IRQS 64 + +/* PIC0 interrupts */ +#define INT_ADMA1 0 +#define INT_BDMA 1 +#define INT_ADMA0 2 +#define INT_GDMA1 3 +#define INT_I2S0RX 4 +#define INT_I2S0TX 5 +#define INT_TC 6 +#define INT_UART0 7 +#define INT_USBD 8 +#define INT_SPI0TX 9 +#define INT_UDMA 10 +#define INT_LIRQ 11 +#define INT_GDMA2 12 +#define INT_GDMA0 13 +#define INT_TC32 14 +#define INT_LCD 15 +#define INT_ADC 16 +#define INT_I2C 17 +#define INT_RTCP 18 +#define INT_RTCA 19 +#define INT_NFC 20 +#define INT_SD0 21 +#define INT_GSB0 22 +#define INT_PK 23 +#define INT_USBH0 24 +#define INT_USBH1 25 +#define INT_G2D 26 +#define INT_ECC 27 +#define INT_SPI0RX 28 +#define INT_UART1 29 +#define INT_MSCL 30 +#define INT_GSB1 31 +/* PIC1 interrupts */ +#define INT_E0 32 +#define INT_E1 33 +#define INT_E2 34 +#define INT_E3 35 +#define INT_E4 36 +#define INT_E5 37 +#define INT_E6 38 +#define INT_E7 39 +#define INT_UART2 40 +#define INT_UART3 41 +#define INT_SPI1TX 42 +#define INT_SPI1RX 43 +#define INT_GSB2 44 +#define INT_SPDIF 45 +#define INT_CDIF 46 +#define INT_VBON 47 +#define INT_VBOFF 48 +#define INT_SD1 49 +#define INT_UART4 50 +#define INT_GDMA3 51 +#define INT_I2S1RX 52 +#define INT_I2S1TX 53 +#define INT_CAN0 54 +#define INT_CAN1 55 +#define INT_GSB3 56 +#define INT_KRST 57 +#define INT_UNUSED 58 +#define INT_SD0D3 59 +#define INT_SD1D3 60 +#define INT_GPS0 61 +#define INT_GPS1 62 +#define INT_GPS2 63 + +#endif /* ASM_ARCH_TCC_IRQS_H */ diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h new file mode 100644 index 0000000..cd91ba8 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/memory.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 1999 ARM Limited + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2008-2009 Telechips + * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GPL v2. + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* + * Physical DRAM offset. + */ +#define PHYS_OFFSET UL(0x20000000) + +#endif diff --git a/arch/arm/plat-tcc/include/mach/system.h b/arch/arm/plat-tcc/include/mach/system.h new file mode 100644 index 0000000..909e603 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/system.h @@ -0,0 +1,31 @@ +/* + * Author: <linux@telechips.com> + * Created: June 10, 2008 + * Description: LINUX SYSTEM FUNCTIONS for TCC83x + * + * Copyright (C) 2008-2009 Telechips + * + * Licensed under the terms of the GPL v2. + * + */ + +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H +#include <linux/clk.h> + +#include <asm/mach-types.h> +#include <mach/hardware.h> + +extern void plat_tcc_reboot(void); + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ + plat_tcc_reboot(); +} + +#endif diff --git a/arch/arm/plat-tcc/include/mach/tcc8k-regs.h b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h new file mode 100644 index 0000000..1d94282 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h @@ -0,0 +1,807 @@ +/* + * Telechips TCC8000 register definitions + * + * (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GPLv2. + */ + +#ifndef TCC8K_REGS_H +#define TCC8K_REGS_H + +#include <linux/types.h> + +#define EXT_SDRAM_BASE 0x20000000 +#define INT_SRAM_BASE 0x30000000 +#define INT_SRAM_SIZE SZ_32K +#define CS0_BASE 0x40000000 +#define CS1_BASE 0x50000000 +#define CS1_SIZE SZ_64K +#define CS2_BASE 0x60000000 +#define CS3_BASE 0x70000000 +#define AHB_PERI_BASE 0x80000000 +#define AHB_PERI_SIZE SZ_64K +#define APB0_PERI_BASE 0x90000000 +#define APB0_PERI_SIZE SZ_128K +#define APB1_PERI_BASE 0x98000000 +#define APB1_PERI_SIZE SZ_128K +#define DATA_TCM_BASE 0xa0000000 +#define DATA_TCM_SIZE SZ_8K +#define EXT_MEM_CTRL_BASE 0xf0000000 +#define EXT_MEM_CTRL_SIZE SZ_4K + +#define CS1_BASE_VIRT (void __iomem *)0xf7000000 +#define AHB_PERI_BASE_VIRT (void __iomem *)0xf4000000 +#define APB0_PERI_BASE_VIRT (void __iomem *)0xf1000000 +#define APB1_PERI_BASE_VIRT (void __iomem *)0xf2000000 +#define EXT_MEM_CTRL_BASE_VIRT (void __iomem *)0xf3000000 +#define INT_SRAM_BASE_VIRT (void __iomem *)0xf5000000 +#define DATA_TCM_BASE_VIRT (void __iomem *)0xf6000000 + +#define __REG(x) (*((volatile u32 *)(x))) + +/* USB Device Controller Registers */ +#define UDC_BASE (AHB_PERI_BASE_VIRT + 0x8000) +#define UDC_BASE_PHYS (AHB_PERI_BASE + 0x8000) + +#define UDC_IR_OFFS 0x00 +#define UDC_EIR_OFFS 0x04 +#define UDC_EIER_OFFS 0x08 +#define UDC_FAR_OFFS 0x0c +#define UDC_FNR_OFFS 0x10 +#define UDC_EDR_OFFS 0x14 +#define UDC_RT_OFFS 0x18 +#define UDC_SSR_OFFS 0x1c +#define UDC_SCR_OFFS 0x20 +#define UDC_EP0SR_OFFS 0x24 +#define UDC_EP0CR_OFFS 0x28 + +#define UDC_ESR_OFFS 0x2c +#define UDC_ECR_OFFS 0x30 +#define UDC_BRCR_OFFS 0x34 +#define UDC_BWCR_OFFS 0x38 +#define UDC_MPR_OFFS 0x3c +#define UDC_DCR_OFFS 0x40 +#define UDC_DTCR_OFFS 0x44 +#define UDC_DFCR_OFFS 0x48 +#define UDC_DTTCR1_OFFS 0x4c +#define UDC_DTTCR2_OFFS 0x50 +#define UDC_ESR2_OFFS 0x54 + +#define UDC_SCR2_OFFS 0x58 +#define UDC_EP0BUF_OFFS 0x60 +#define UDC_EP1BUF_OFFS 0x64 +#define UDC_EP2BUF_OFFS 0x68 +#define UDC_EP3BUF_OFFS 0x6c +#define UDC_PLICR_OFFS 0xa0 +#define UDC_PCR_OFFS 0xa4 + +#define UDC_UPCR0_OFFS 0xc8 +#define UDC_UPCR1_OFFS 0xcc +#define UDC_UPCR2_OFFS 0xd0 +#define UDC_UPCR3_OFFS 0xd4 + +/* Bits in UDC_EIR */ +#define UDC_EIR_EP0I (1 << 0) +#define UDC_EIR_EP1I (1 << 1) +#define UDC_EIR_EP2I (1 << 2) +#define UDC_EIR_EP3I (1 << 3) +#define UDC_EIR_EPI_MASK 0x0f + +/* Bits in UDC_EIER */ +#define UDC_EIER_EP0IE (1 << 0) +#define UDC_EIER_EP1IE (1 << 1) +#define UDC_EIER_EP2IE (1 << 2) +#define UDC_EIER_EP3IE (1 << 3) + +/* Bits in UDC_FNR */ +#define UDC_FNR_FN_MASK 0x7ff +#define UDC_FNR_SM (1 << 13) +#define UDC_FNR_FTL (1 << 14) + +/* Bits in UDC_SSR */ +#define UDC_SSR_HFRES (1 << 0) +#define UDC_SSR_HFSUSP (1 << 1) +#define UDC_SSR_HFRM (1 << 2) +#define UDC_SSR_SDE (1 << 3) +#define UDC_SSR_HSP (1 << 4) +#define UDC_SSR_DM (1 << 5) +#define UDC_SSR_DP (1 << 6) +#define UDC_SSR_TBM (1 << 7) +#define UDC_SSR_VBON (1 << 8) +#define UDC_SSR_VBOFF (1 << 9) +#define UDC_SSR_EOERR (1 << 10) +#define UDC_SSR_DCERR (1 << 11) +#define UDC_SSR_TCERR (1 << 12) +#define UDC_SSR_BSERR (1 << 13) +#define UDC_SSR_TMERR (1 << 14) +#define UDC_SSR_BAERR (1 << 15) + +/* Bits in UDC_SCR */ +#define UDC_SCR_HRESE (1 << 0) +#define UDC_SCR_HSSPE (1 << 1) +#define UDC_SCR_RRDE (1 << 5) +#define UDC_SCR_SPDEN (1 << 6) +#define UDC_SCR_DIEN (1 << 12) + +/* Bits in UDC_EP0SR */ +#define UDC_EP0SR_RSR (1 << 0) +#define UDC_EP0SR_TST (1 << 1) +#define UDC_EP0SR_SHT (1 << 4) +#define UDC_EP0SR_LWO (1 << 6) + +/* Bits in UDC_EP0CR */ +#define UDC_EP0CR_ESS (1 << 1) + +/* Bits in UDC_ESR */ +#define UDC_ESR_RPS (1 << 0) +#define UDC_ESR_TPS (1 << 1) +#define UDC_ESR_LWO (1 << 4) +#define UDC_ESR_FFS (1 << 6) + +/* Bits in UDC_ECR */ +#define UDC_ECR_ESS (1 << 1) +#define UDC_ECR_CDP (1 << 2) + +#define UDC_ECR_FLUSH (1 << 6) +#define UDC_ECR_DUEN (1 << 7) + +/* Bits in UDC_UPCR0 */ +#define UDC_UPCR0_VBD (1 << 1) +#define UDC_UPCR0_VBDS (1 << 6) +#define UDC_UPCR0_RCD_12 (0x0 << 9) +#define UDC_UPCR0_RCD_24 (0x1 << 9) +#define UDC_UPCR0_RCD_48 (0x2 << 9) +#define UDC_UPCR0_RCS_EXT (0x1 << 11) +#define UDC_UPCR0_RCS_XTAL (0x0 << 11) + +/* Bits in UDC_UPCR1 */ +#define UDC_UPCR1_CDT(x) ((x) << 0) +#define UDC_UPCR1_OTGT(x) ((x) << 3) +#define UDC_UPCR1_SQRXT(x) ((x) << 8) +#define UDC_UPCR1_TXFSLST(x) ((x) << 12) + +/* Bits in UDC_UPCR2 */ +#define UDC_UPCR2_TP (1 << 0) +#define UDC_UPCR2_TXRT(x) ((x) << 2) +#define UDC_UPCR2_TXVRT(x) ((x) << 5) +#define UDC_UPCR2_OPMODE(x) ((x) << 9) +#define UDC_UPCR2_XCVRSEL(x) ((x) << 12) +#define UDC_UPCR2_TM (1 << 14) + +/* USB Host Controller registers */ +#define USBH0_BASE (AHB_PERI_BASE_VIRT + 0xb000) +#define USBH1_BASE (AHB_PERI_BASE_VIRT + 0xb800) + +#define OHCI_INT_ENABLE_OFFS 0x10 + +#define RH_DESCRIPTOR_A_OFFS 0x48 +#define RH_DESCRIPTOR_B_OFFS 0x4c + +#define USBHTCFG0_OFFS 0x100 +#define USBHHCFG0_OFFS 0x104 +#define USBHHCFG1_OFFS 0x104 + +/* DMA controller registers */ +#define DMAC0_BASE (AHB_PERI_BASE + 0x4000) +#define DMAC1_BASE (AHB_PERI_BASE + 0xa000) +#define DMAC2_BASE (AHB_PERI_BASE + 0x4800) +#define DMAC3_BASE (AHB_PERI_BASE + 0xa800) + +#define DMAC_CH_OFFSET(ch) (ch * 0x30) + +#define ST_SADR_OFFS 0x00 +#define SPARAM_OFFS 0x04 +#define C_SADR_OFFS 0x0c +#define ST_DADR_OFFS 0x10 +#define DPARAM_OFFS 0x14 +#define C_DADR_OFFS 0x1c +#define HCOUNT_OFFS 0x20 +#define CHCTRL_OFFS 0x24 +#define RPTCTRL_OFFS 0x28 +#define EXTREQ_A_OFFS 0x2c + +/* Bits in CHCTRL register */ +#define CHCTRL_EN (1 << 0) + +#define CHCTRL_IEN (1 << 2) +#define CHCTRL_FLAG (1 << 3) +#define CHCTRL_WSIZE8 (0 << 4) +#define CHCTRL_WSIZE16 (1 << 4) +#define CHCTRL_WSIZE32 (2 << 4) + +#define CHCTRL_BSIZE1 (0 << 6) +#define CHCTRL_BSIZE2 (1 << 6) +#define CHCTRL_BSIZE4 (2 << 6) +#define CHCTRL_BSIZE8 (3 << 6) + +#define CHCTRL_TYPE_SINGLE_E (0 << 8) +#define CHCTRL_TYPE_HW (1 << 8) +#define CHCTRL_TYPE_SW (2 << 8) +#define CHCTRL_TYPE_SINGLE_L (3 << 8) + +#define CHCTRL_BST (1 << 10) + +/* Use DMA controller 0, channel 2 for USB */ +#define USB_DMA_BASE (DMAC0_BASE + DMAC_CH_OFFSET(2)) + +/* NAND flash controller registers */ +#define NFC_BASE (AHB_PERI_BASE_VIRT + 0xd000) +#define NFC_BASE_PHYS (AHB_PERI_BASE + 0xd000) + +#define NFC_CMD_OFFS 0x00 +#define NFC_LADDR_OFFS 0x04 +#define NFC_BADDR_OFFS 0x08 +#define NFC_SADDR_OFFS 0x0c +#define NFC_WDATA_OFFS 0x10 +#define NFC_LDATA_OFFS 0x20 +#define NFC_SDATA_OFFS 0x40 +#define NFC_CTRL_OFFS 0x50 +#define NFC_PSTART_OFFS 0x54 +#define NFC_RSTART_OFFS 0x58 +#define NFC_DSIZE_OFFS 0x5c +#define NFC_IREQ_OFFS 0x60 +#define NFC_RST_OFFS 0x64 +#define NFC_CTRL1_OFFS 0x68 +#define NFC_MDATA_OFFS 0x70 + +#define NFC_WDATA_PHYS_ADDR (NFC_BASE_PHYS + NFC_WDATA_OFFS) + +/* Bits in NFC_CTRL */ +#define NFC_CTRL_BHLD_MASK (0xf << 0) +#define NFC_CTRL_BPW_MASK (0xf << 4) +#define NFC_CTRL_BSTP_MASK (0xf << 8) +#define NFC_CTRL_CADDR_MASK (0x7 << 12) +#define NFC_CTRL_CADDR_1 (0x0 << 12) +#define NFC_CTRL_CADDR_2 (0x1 << 12) +#define NFC_CTRL_CADDR_3 (0x2 << 12) +#define NFC_CTRL_CADDR_4 (0x3 << 12) +#define NFC_CTRL_CADDR_5 (0x4 << 12) +#define NFC_CTRL_MSK (1 << 15) +#define NFC_CTRL_PSIZE256 (0 << 16) +#define NFC_CTRL_PSIZE512 (1 << 16) +#define NFC_CTRL_PSIZE1024 (2 << 16) +#define NFC_CTRL_PSIZE2048 (3 << 16) +#define NFC_CTRL_PSIZE4096 (4 << 16) +#define NFC_CTRL_PSIZE_MASK (7 << 16) +#define NFC_CTRL_BSIZE1 (0 << 19) +#define NFC_CTRL_BSIZE2 (1 << 19) +#define NFC_CTRL_BSIZE4 (2 << 19) +#define NFC_CTRL_BSIZE8 (3 << 19) +#define NFC_CTRL_BSIZE_MASK (3 << 19) +#define NFC_CTRL_RDY (1 << 21) +#define NFC_CTRL_CS0SEL (1 << 22) +#define NFC_CTRL_CS1SEL (1 << 23) +#define NFC_CTRL_CS2SEL (1 << 24) +#define NFC_CTRL_CS3SEL (1 << 25) +#define NFC_CTRL_CSMASK (0xf << 22) +#define NFC_CTRL_BW (1 << 26) +#define NFC_CTRL_FS (1 << 27) +#define NFC_CTRL_DEN (1 << 28) +#define NFC_CTRL_READ_IEN (1 << 29) +#define NFC_CTRL_PROG_IEN (1 << 30) +#define NFC_CTRL_RDY_IEN (1 << 31) + +/* Bits in NFC_IREQ */ +#define NFC_IREQ_IRQ0 (1 << 0) +#define NFC_IREQ_IRQ1 (1 << 1) +#define NFC_IREQ_IRQ2 (1 << 2) + +#define NFC_IREQ_FLAG0 (1 << 4) +#define NFC_IREQ_FLAG1 (1 << 5) +#define NFC_IREQ_FLAG2 (1 << 6) + +/* MMC controller registers */ +#define MMC0_BASE (AHB_PERI_BASE_VIRT + 0xe000) +#define MMC1_BASE (AHB_PERI_BASE_VIRT + 0xe800) + +/* UART base addresses */ + +#define UART0_BASE (APB0_PERI_BASE_VIRT + 0x07000) +#define UART0_BASE_PHYS (APB0_PERI_BASE + 0x07000) +#define UART1_BASE (APB0_PERI_BASE_VIRT + 0x08000) +#define UART1_BASE_PHYS (APB0_PERI_BASE + 0x08000) +#define UART2_BASE (APB0_PERI_BASE_VIRT + 0x09000) +#define UART2_BASE_PHYS (APB0_PERI_BASE + 0x09000) +#define UART3_BASE (APB0_PERI_BASE_VIRT + 0x0a000) +#define UART3_BASE_PHYS (APB0_PERI_BASE + 0x0a000) +#define UART4_BASE (APB0_PERI_BASE_VIRT + 0x15000) +#define UART4_BASE_PHYS (APB0_PERI_BASE + 0x15000) + +#define UART_BASE UART0_BASE +#define UART_BASE_PHYS UART0_BASE_PHYS + +/* ECC controller */ +#define ECC_CTR_BASE (APB0_PERI_BASE_VIRT + 0xd000) + +#define ECC_CTRL_OFFS 0x00 +#define ECC_BASE_OFFS 0x04 +#define ECC_MASK_OFFS 0x08 +#define ECC_CLEAR_OFFS 0x0c +#define ECC4_0_OFFS 0x10 +#define ECC4_1_OFFS 0x14 + +#define ECC_EADDR0_OFFS 0x50 + +#define ECC_ERRNUM_OFFS 0x90 +#define ECC_IREQ_OFFS 0x94 + +/* Bits in ECC_CTRL */ +#define ECC_CTRL_ECC4_DIEN (1 << 28) +#define ECC_CTRL_ECC8_DIEN (1 << 29) +#define ECC_CTRL_ECC12_DIEN (1 << 30) +#define ECC_CTRL_ECC_DISABLE 0x0 +#define ECC_CTRL_ECC_SLC_ENC 0x8 +#define ECC_CTRL_ECC_SLC_DEC 0x9 +#define ECC_CTRL_ECC4_ENC 0xa +#define ECC_CTRL_ECC4_DEC 0xb +#define ECC_CTRL_ECC8_ENC 0xc +#define ECC_CTRL_ECC8_DEC 0xd +#define ECC_CTRL_ECC12_ENC 0xe +#define ECC_CTRL_ECC12_DEC 0xf + +/* Bits in ECC_IREQ */ +#define ECC_IREQ_E4DI (1 << 4) + +#define ECC_IREQ_E4DF (1 << 20) +#define ECC_IREQ_E4EF (1 << 21) + +/* Interrupt controller */ + +#define PIC0_BASE (APB1_PERI_BASE_VIRT + 0x3000) +#define PIC0_BASE_PHYS (APB1_PERI_BASE + 0x3000) + +#define PIC0_IEN_OFFS 0x00 +#define PIC0_CREQ_OFFS 0x04 +#define PIC0_IREQ_OFFS 0x08 +#define PIC0_IRQSEL_OFFS 0x0c +#define PIC0_SRC_OFFS 0x10 +#define PIC0_MREQ_OFFS 0x14 +#define PIC0_TSTREQ_OFFS 0x18 +#define PIC0_POL_OFFS 0x1c +#define PIC0_IRQ_OFFS 0x20 +#define PIC0_FIQ_OFFS 0x24 +#define PIC0_MIRQ_OFFS 0x28 +#define PIC0_MFIQ_OFFS 0x2c +#define PIC0_TMODE_OFFS 0x30 +#define PIC0_SYNC_OFFS 0x34 +#define PIC0_WKUP_OFFS 0x38 +#define PIC0_TMODEA_OFFS 0x3c +#define PIC0_INTOEN_OFFS 0x40 +#define PIC0_MEN0_OFFS 0x44 +#define PIC0_MEN_OFFS 0x48 + +#define PIC0_IEN __REG(PIC0_BASE + PIC0_IEN_OFFS) +#define PIC0_IEN_PHYS __REG(PIC0_BASE_PHYS + PIC0_IEN_OFFS) +#define PIC0_CREQ __REG(PIC0_BASE + PIC0_CREQ_OFFS) +#define PIC0_CREQ_PHYS __REG(PIC0_BASE_PHYS + PIC0_CREQ_OFFS) +#define PIC0_IREQ __REG(PIC0_BASE + PIC0_IREQ_OFFS) +#define PIC0_IRQSEL __REG(PIC0_BASE + PIC0_IRQSEL_OFFS) +#define PIC0_IRQSEL_PHYS __REG(PIC0_BASE_PHYS + PIC0_IRQSEL_OFFS) +#define PIC0_SRC __REG(PIC0_BASE + PIC0_SRC_OFFS) +#define PIC0_MREQ __REG(PIC0_BASE + PIC0_MREQ_OFFS) +#define PIC0_TSTREQ __REG(PIC0_BASE + PIC0_TSTREQ_OFFS) +#define PIC0_POL __REG(PIC0_BASE + PIC0_POL_OFFS) +#define PIC0_IRQ __REG(PIC0_BASE + PIC0_IRQ_OFFS) +#define PIC0_FIQ __REG(PIC0_BASE + PIC0_FIQ_OFFS) +#define PIC0_MIRQ __REG(PIC0_BASE + PIC0_MIRQ_OFFS) +#define PIC0_MFIQ __REG(PIC0_BASE + PIC0_MFIQ_OFFS) +#define PIC0_TMODE __REG(PIC0_BASE + PIC0_TMODE_OFFS) +#define PIC0_TMODE_PHYS __REG(PIC0_BASE_PHYS + PIC0_TMODE_OFFS) +#define PIC0_SYNC __REG(PIC0_BASE + PIC0_SYNC_OFFS) +#define PIC0_WKUP __REG(PIC0_BASE + PIC0_WKUP_OFFS) +#define PIC0_TMODEA __REG(PIC0_BASE + PIC0_TMODEA_OFFS) +#define PIC0_INTOEN __REG(PIC0_BASE + PIC0_INTOEN_OFFS) +#define PIC0_MEN0 __REG(PIC0_BASE + PIC0_MEN0_OFFS) +#define PIC0_MEN __REG(PIC0_BASE + PIC0_MEN_OFFS) + +#define PIC1_BASE (APB1_PERI_BASE_VIRT + 0x3080) + +#define PIC1_IEN_OFFS 0x00 +#define PIC1_CREQ_OFFS 0x04 +#define PIC1_IREQ_OFFS 0x08 +#define PIC1_IRQSEL_OFFS 0x0c +#define PIC1_SRC_OFFS 0x10 +#define PIC1_MREQ_OFFS 0x14 +#define PIC1_TSTREQ_OFFS 0x18 +#define PIC1_POL_OFFS 0x1c +#define PIC1_IRQ_OFFS 0x20 +#define PIC1_FIQ_OFFS 0x24 +#define PIC1_MIRQ_OFFS 0x28 +#define PIC1_MFIQ_OFFS 0x2c +#define PIC1_TMODE_OFFS 0x30 +#define PIC1_SYNC_OFFS 0x34 +#define PIC1_WKUP_OFFS 0x38 +#define PIC1_TMODEA_OFFS 0x3c +#define PIC1_INTOEN_OFFS 0x40 +#define PIC1_MEN1_OFFS 0x44 +#define PIC1_MEN_OFFS 0x48 + +#define PIC1_IEN __REG(PIC1_BASE + PIC1_IEN_OFFS) +#define PIC1_CREQ __REG(PIC1_BASE + PIC1_CREQ_OFFS) +#define PIC1_IREQ __REG(PIC1_BASE + PIC1_IREQ_OFFS) +#define PIC1_IRQSEL __REG(PIC1_BASE + PIC1_IRQSEL_OFFS) +#define PIC1_SRC __REG(PIC1_BASE + PIC1_SRC_OFFS) +#define PIC1_MREQ __REG(PIC1_BASE + PIC1_MREQ_OFFS) +#define PIC1_TSTREQ __REG(PIC1_BASE + PIC1_TSTREQ_OFFS) +#define PIC1_POL __REG(PIC1_BASE + PIC1_POL_OFFS) +#define PIC1_IRQ __REG(PIC1_BASE + PIC1_IRQ_OFFS) +#define PIC1_FIQ __REG(PIC1_BASE + PIC1_FIQ_OFFS) +#define PIC1_MIRQ __REG(PIC1_BASE + PIC1_MIRQ_OFFS) +#define PIC1_MFIQ __REG(PIC1_BASE + PIC1_MFIQ_OFFS) +#define PIC1_TMODE __REG(PIC1_BASE + PIC1_TMODE_OFFS) +#define PIC1_SYNC __REG(PIC1_BASE + PIC1_SYNC_OFFS) +#define PIC1_WKUP __REG(PIC1_BASE + PIC1_WKUP_OFFS) +#define PIC1_TMODEA __REG(PIC1_BASE + PIC1_TMODEA_OFFS) +#define PIC1_INTOEN __REG(PIC1_BASE + PIC1_INTOEN_OFFS) +#define PIC1_MEN1 __REG(PIC1_BASE + PIC1_MEN1_OFFS) +#define PIC1_MEN __REG(PIC1_BASE + PIC1_MEN_OFFS) + +/* Timer registers */ +#define TIMER_BASE (APB1_PERI_BASE_VIRT + 0x4000) +#define TIMER_BASE_PHYS (APB1_PERI_BASE + 0x4000) + +#define TWDCFG_OFFS 0x70 + +#define TC32EN_OFFS 0x80 +#define TC32LDV_OFFS 0x84 +#define TC32CMP0_OFFS 0x88 +#define TC32CMP1_OFFS 0x8c +#define TC32PCNT_OFFS 0x90 +#define TC32MCNT_OFFS 0x94 +#define TC32IRQ_OFFS 0x98 + +/* Bits in TC32EN */ +#define TC32EN_PRESCALE_MASK 0x00ffffff +#define TC32EN_ENABLE (1 << 24) +#define TC32EN_LOADZERO (1 << 25) +#define TC32EN_STOPMODE (1 << 26) +#define TC32EN_LDM0 (1 << 28) +#define TC32EN_LDM1 (1 << 29) + +/* Bits in TC32IRQ */ +#define TC32IRQ_MSTAT_MASK 0x0000001f +#define TC32IRQ_RSTAT_MASK (0x1f << 8) +#define TC32IRQ_IRQEN0 (1 << 16) +#define TC32IRQ_IRQEN1 (1 << 17) +#define TC32IRQ_IRQEN2 (1 << 18) +#define TC32IRQ_IRQEN3 (1 << 19) +#define TC32IRQ_IRQEN4 (1 << 20) +#define TC32IRQ_RSYNC (1 << 30) +#define TC32IRQ_IRQCLR (1 << 31) + +/* GPIO registers */ +#define GPIOPD_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOPD_DAT_OFFS 0x00 +#define GPIOPD_DOE_OFFS 0x04 +#define GPIOPD_FS0_OFFS 0x08 +#define GPIOPD_FS1_OFFS 0x0c +#define GPIOPD_FS2_OFFS 0x10 +#define GPIOPD_RPU_OFFS 0x30 +#define GPIOPD_RPD_OFFS 0x34 +#define GPIOPD_DV0_OFFS 0x38 +#define GPIOPD_DV1_OFFS 0x3c + +#define GPIOPS_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOPS_DAT_OFFS 0x40 +#define GPIOPS_DOE_OFFS 0x44 +#define GPIOPS_FS0_OFFS 0x48 +#define GPIOPS_FS1_OFFS 0x4c +#define GPIOPS_FS2_OFFS 0x50 +#define GPIOPS_FS3_OFFS 0x54 +#define GPIOPS_RPU_OFFS 0x70 +#define GPIOPS_RPD_OFFS 0x74 +#define GPIOPS_DV0_OFFS 0x78 +#define GPIOPS_DV1_OFFS 0x7c + +#define GPIOPS_FS1_SDH0_BITS 0x000000ff +#define GPIOPS_FS1_SDH1_BITS 0x0000ff00 + +#define GPIOPU_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOPU_DAT_OFFS 0x80 +#define GPIOPU_DOE_OFFS 0x84 +#define GPIOPU_FS0_OFFS 0x88 +#define GPIOPU_FS1_OFFS 0x8c +#define GPIOPU_FS2_OFFS 0x90 +#define GPIOPU_RPU_OFFS 0xb0 +#define GPIOPU_RPD_OFFS 0xb4 +#define GPIOPU_DV0_OFFS 0xb8 +#define GPIOPU_DV1_OFFS 0xbc + +#define GPIOPU_FS0_TXD0 (1 << 0) +#define GPIOPU_FS0_RXD0 (1 << 1) +#define GPIOPU_FS0_CTS0 (1 << 2) +#define GPIOPU_FS0_RTS0 (1 << 3) +#define GPIOPU_FS0_TXD1 (1 << 4) +#define GPIOPU_FS0_RXD1 (1 << 5) +#define GPIOPU_FS0_CTS1 (1 << 6) +#define GPIOPU_FS0_RTS1 (1 << 7) +#define GPIOPU_FS0_TXD2 (1 << 8) +#define GPIOPU_FS0_RXD2 (1 << 9) +#define GPIOPU_FS0_CTS2 (1 << 10) +#define GPIOPU_FS0_RTS2 (1 << 11) +#define GPIOPU_FS0_TXD3 (1 << 12) +#define GPIOPU_FS0_RXD3 (1 << 13) +#define GPIOPU_FS0_CTS3 (1 << 14) +#define GPIOPU_FS0_RTS3 (1 << 15) +#define GPIOPU_FS0_TXD4 (1 << 16) +#define GPIOPU_FS0_RXD4 (1 << 17) +#define GPIOPU_FS0_CTS4 (1 << 18) +#define GPIOPU_FS0_RTS4 (1 << 19) + +#define GPIOFC_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOFC_DAT_OFFS 0xc0 +#define GPIOFC_DOE_OFFS 0xc4 +#define GPIOFC_FS0_OFFS 0xc8 +#define GPIOFC_FS1_OFFS 0xcc +#define GPIOFC_FS2_OFFS 0xd0 +#define GPIOFC_FS3_OFFS 0xd4 +#define GPIOFC_RPU_OFFS 0xf0 +#define GPIOFC_RPD_OFFS 0xf4 +#define GPIOFC_DV0_OFFS 0xf8 +#define GPIOFC_DV1_OFFS 0xfc + +#define GPIOFD_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOFD_DAT_OFFS 0x100 +#define GPIOFD_DOE_OFFS 0x104 +#define GPIOFD_FS0_OFFS 0x108 +#define GPIOFD_FS1_OFFS 0x10c +#define GPIOFD_FS2_OFFS 0x110 +#define GPIOFD_RPU_OFFS 0x130 +#define GPIOFD_RPD_OFFS 0x134 +#define GPIOFD_DV0_OFFS 0x138 +#define GPIOFD_DV1_OFFS 0x13c + +#define GPIOLC_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOLC_DAT_OFFS 0x140 +#define GPIOLC_DOE_OFFS 0x144 +#define GPIOLC_FS0_OFFS 0x148 +#define GPIOLC_FS1_OFFS 0x14c +#define GPIOLC_RPU_OFFS 0x170 +#define GPIOLC_RPD_OFFS 0x174 +#define GPIOLC_DV0_OFFS 0x178 +#define GPIOLC_DV1_OFFS 0x17c + +#define GPIOLD_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOLD_DAT_OFFS 0x180 +#define GPIOLD_DOE_OFFS 0x184 +#define GPIOLD_FS0_OFFS 0x188 +#define GPIOLD_FS1_OFFS 0x18c +#define GPIOLD_FS2_OFFS 0x190 +#define GPIOLD_RPU_OFFS 0x1b0 +#define GPIOLD_RPD_OFFS 0x1b4 +#define GPIOLD_DV0_OFFS 0x1b8 +#define GPIOLD_DV1_OFFS 0x1bc + +#define GPIOAD_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOAD_DAT_OFFS 0x1c0 +#define GPIOAD_DOE_OFFS 0x1c4 +#define GPIOAD_FS0_OFFS 0x1c8 +#define GPIOAD_RPU_OFFS 0x1f0 +#define GPIOAD_RPD_OFFS 0x1f4 +#define GPIOAD_DV0_OFFS 0x1f8 +#define GPIOAD_DV1_OFFS 0x1fc + +#define GPIOXC_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOXC_DAT_OFFS 0x200 +#define GPIOXC_DOE_OFFS 0x204 +#define GPIOXC_FS0_OFFS 0x208 +#define GPIOXC_RPU_OFFS 0x230 +#define GPIOXC_RPD_OFFS 0x234 +#define GPIOXC_DV0_OFFS 0x238 +#define GPIOXC_DV1_OFFS 0x23c + +#define GPIOXC_FS0 __REG(GPIOXC_BASE + GPIOXC_FS0_OFFS) + +#define GPIOXC_FS0_CS0 (1 << 26) +#define GPIOXC_FS0_CS1 (1 << 27) + +#define GPIOXD_BASE (APB1_PERI_BASE_VIRT + 0x5000) + +#define GPIOXD_DAT_OFFS 0x240 +#define GPIOXD_FS0_OFFS 0x248 +#define GPIOXD_RPU_OFFS 0x270 +#define GPIOXD_RPD_OFFS 0x274 +#define GPIOXD_DV0_OFFS 0x278 +#define GPIOXD_DV1_OFFS 0x27c + +#define GPIOPK_BASE (APB1_PERI_BASE_VIRT + 0x1c000) + +#define GPIOPK_RST_OFFS 0x008 +#define GPIOPK_DAT_OFFS 0x100 +#define GPIOPK_DOE_OFFS 0x104 +#define GPIOPK_FS0_OFFS 0x108 +#define GPIOPK_FS1_OFFS 0x10c +#define GPIOPK_FS2_OFFS 0x110 +#define GPIOPK_IRQST_OFFS 0x210 +#define GPIOPK_IRQEN_OFFS 0x214 +#define GPIOPK_IRQPOL_OFFS 0x218 +#define GPIOPK_IRQTM0_OFFS 0x21c +#define GPIOPK_IRQTM1_OFFS 0x220 +#define GPIOPK_CTL_OFFS 0x22c + +#define PMGPIO_BASE (APB1_PERI_BASE_VIRT + 0x10000) +#define BACKUP_RAM_BASE PMGPIO_BASE + +#define PMGPIO_DAT_OFFS 0x800 +#define PMGPIO_DOE_OFFS 0x804 +#define PMGPIO_FS0_OFFS 0x808 +#define PMGPIO_RPU_OFFS 0x810 +#define PMGPIO_RPD_OFFS 0x814 +#define PMGPIO_DV0_OFFS 0x818 +#define PMGPIO_DV1_OFFS 0x81c +#define PMGPIO_EE0_OFFS 0x820 +#define PMGPIO_EE1_OFFS 0x824 +#define PMGPIO_CTL_OFFS 0x828 +#define PMGPIO_DI_OFFS 0x82c +#define PMGPIO_STR_OFFS 0x830 +#define PMGPIO_STF_OFFS 0x834 +#define PMGPIO_POL_OFFS 0x838 +#define PMGPIO_APB_OFFS 0x800 + +/* Clock controller registers */ +#define CKC_BASE ((void __iomem *)(APB1_PERI_BASE_VIRT + 0x6000)) + +#define CLKCTRL_OFFS 0x00 +#define PLL0CFG_OFFS 0x04 +#define PLL1CFG_OFFS 0x08 +#define CLKDIVC0_OFFS 0x0c + +#define BCLKCTR0_OFFS 0x14 +#define SWRESET0_OFFS 0x18 + +#define BCLKCTR1_OFFS 0x60 +#define SWRESET1_OFFS 0x64 +#define PWDCTL_OFFS 0x68 +#define PLL2CFG_OFFS 0x6c +#define CLKDIVC1_OFFS 0x70 + +#define ACLKREF_OFFS 0x80 +#define ACLKI2C_OFFS 0x84 +#define ACLKSPI0_OFFS 0x88 +#define ACLKSPI1_OFFS 0x8c +#define ACLKUART0_OFFS 0x90 +#define ACLKUART1_OFFS 0x94 +#define ACLKUART2_OFFS 0x98 +#define ACLKUART3_OFFS 0x9c +#define ACLKUART4_OFFS 0xa0 +#define ACLKTCT_OFFS 0xa4 +#define ACLKTCX_OFFS 0xa8 +#define ACLKTCZ_OFFS 0xac +#define ACLKADC_OFFS 0xb0 +#define ACLKDAI0_OFFS 0xb4 +#define ACLKDAI1_OFFS 0xb8 +#define ACLKLCD_OFFS 0xbc +#define ACLKSPDIF_OFFS 0xc0 +#define ACLKUSBH_OFFS 0xc4 +#define ACLKSDH0_OFFS 0xc8 +#define ACLKSDH1_OFFS 0xcc +#define ACLKC3DEC_OFFS 0xd0 +#define ACLKEXT_OFFS 0xd4 +#define ACLKCAN0_OFFS 0xd8 +#define ACLKCAN1_OFFS 0xdc +#define ACLKGSB0_OFFS 0xe0 +#define ACLKGSB1_OFFS 0xe4 +#define ACLKGSB2_OFFS 0xe8 +#define ACLKGSB3_OFFS 0xec + +#define PLLxCFG_PD (1 << 31) + +/* CLKCTRL bits */ +#define CLKCTRL_XE (1 << 31) + +/* CLKDIVCx bits */ +#define CLKDIVC0_XTE (1 << 7) +#define CLKDIVC0_XE (1 << 15) +#define CLKDIVC0_P1E (1 << 23) +#define CLKDIVC0_P0E (1 << 31) + +#define CLKDIVC1_P2E (1 << 7) + +/* BCLKCTR0 clock bits */ +#define BCLKCTR0_USBD (1 << 4) +#define BCLKCTR0_ECC (1 << 9) +#define BCLKCTR0_USBH0 (1 << 11) +#define BCLKCTR0_NFC (1 << 16) + +/* BCLKCTR1 clock bits */ +#define BCLKCTR1_USBH1 (1 << 20) + +/* SWRESET0 bits */ +#define SWRESET0_USBD (1 << 4) +#define SWRESET0_USBH0 (1 << 11) + +/* SWRESET1 bits */ +#define SWRESET1_USBH1 (1 << 20) + +/* System clock sources. + * Note: These are the clock sources that serve as parents for + * all other clocks. They have no parents themselves. + * + * These values are used for struct clk->root_id. All clocks + * that are not system clock sources have this value set to + * CLK_SRC_NOROOT. + * The values for system clocks start with CLK_SRC_PLL0 == 0 + * because this gives us exactly the values needed for the lower + * 4 bits of ACLK_* registers. Therefore, CLK_SRC_NOROOT is + * defined as -1 to not disturb the order. + */ +enum root_clks { + CLK_SRC_NOROOT = -1, + CLK_SRC_PLL0 = 0, + CLK_SRC_PLL1, + CLK_SRC_PLL0DIV, + CLK_SRC_PLL1DIV, + CLK_SRC_XI, + CLK_SRC_XIDIV, + CLK_SRC_XTI, + CLK_SRC_XTIDIV, + CLK_SRC_PLL2, + CLK_SRC_PLL2DIV, + CLK_SRC_PK0, + CLK_SRC_PK1, + CLK_SRC_PK2, + CLK_SRC_PK3, + CLK_SRC_PK4, + CLK_SRC_48MHZ +}; + +#define CLK_SRC_MASK 0xf + +/* Bits in ACLK* registers */ +#define ACLK_EN (1 << 28) +#define ACLK_SEL_SHIFT 24 +#define ACLK_SEL_MASK 0x0f000000 +#define ACLK_DIV_MASK 0x00000fff + +/* System configuration registers */ + +#define SCFG_BASE (APB1_PERI_BASE_VIRT + 0x13000) + +#define BMI_OFFS 0x00 +#define AHBCON0_OFFS 0x04 +#define APBPWE_OFFS 0x08 +#define DTCMWAIT_OFFS 0x0c +#define ECCSEL_OFFS 0x10 +#define AHBCON1_OFFS 0x14 +#define SDHCFG_OFFS 0x18 +#define REMAP_OFFS 0x20 +#define LCDSIAE_OFFS 0x24 +#define XMCCFG_OFFS 0xe0 +#define IMCCFG_OFFS 0xe4 + +/* Values for ECCSEL */ +#define ECCSEL_EXTMEM 0x0 +#define ECCSEL_DTCM 0x1 +#define ECCSEL_INT_SRAM 0x2 +#define ECCSEL_AHB 0x3 + +/* Bits in XMCCFG */ +#define XMCCFG_NFCE (1 << 1) +#define XMCCFG_FDXD (1 << 2) + +/* External memory controller registers */ + +#define EMC_BASE EXT_MEM_CTRL_BASE + +#define SDCFG_OFFS 0x00 +#define SDFSM_OFFS 0x04 +#define MCFG_OFFS 0x08 + +#define CSCFG0_OFFS 0x10 +#define CSCFG1_OFFS 0x14 +#define CSCFG2_OFFS 0x18 +#define CSCFG3_OFFS 0x1c + +#define MCFG_SDEN (1 << 4) + +#endif /* TCC8K_REGS_H */ diff --git a/arch/arm/plat-tcc/include/mach/timex.h b/arch/arm/plat-tcc/include/mach/timex.h new file mode 100644 index 0000000..057acbe --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/timex.h @@ -0,0 +1,5 @@ +/* + * A definition needed by arch core code. + * + */ +#define CLOCK_TICK_RATE (HZ * 100000UL) diff --git a/arch/arm/plat-tcc/include/mach/uncompress.h b/arch/arm/plat-tcc/include/mach/uncompress.h new file mode 100644 index 0000000..7a3e33a --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/uncompress.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de> + * + * This file is licensed under the terms of the GPL version 2. + */ + +#include <linux/serial_reg.h> +#include <linux/types.h> + +#include <mach/tcc8k-regs.h> + +unsigned int system_rev; + +#define ID_MASK 0x7fff + +static void putc(int c) +{ + u32 *uart_lsr = (u32 *)(UART_BASE_PHYS + (UART_LSR << 2)); + u32 *uart_tx = (u32 *)(UART_BASE_PHYS + (UART_TX << 2)); + + while (!(*uart_lsr & UART_LSR_THRE)) + barrier(); + *uart_tx = c; +} + +static inline void flush(void) +{ +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/arch/arm/plat-tcc/include/mach/vmalloc.h b/arch/arm/plat-tcc/include/mach/vmalloc.h new file mode 100644 index 0000000..99414d9 --- /dev/null +++ b/arch/arm/plat-tcc/include/mach/vmalloc.h @@ -0,0 +1,10 @@ +/* + * Author: <linux@telechips.com> + * Created: June 10, 2008 + * + * Copyright (C) 2000 Russell King. + * Copyright (C) 2008-2009 Telechips + * + * Licensed under the terms of the GPL v2. + */ +#define VMALLOC_END 0xf0000000UL diff --git a/arch/arm/plat-tcc/system.c b/arch/arm/plat-tcc/system.c new file mode 100644 index 0000000..cc208fa --- /dev/null +++ b/arch/arm/plat-tcc/system.c @@ -0,0 +1,25 @@ +/* + * System functions for Telechips TCCxxxx SoCs + * + * Copyright (C) Hans J. Koch <hjk@linutronix.de> + * + * Licensed under the terms of the GPL v2. + * + */ + +#include <linux/io.h> + +#include <mach/tcc8k-regs.h> + +/* System reboot */ +void plat_tcc_reboot(void) +{ + /* Make sure clocks are on */ + __raw_writel(0xffffffff, CKC_BASE + BCLKCTR0_OFFS); + + /* Enable watchdog reset */ + __raw_writel(0x49, TIMER_BASE + TWDCFG_OFFS); + /* Wait for reset */ + while(1) + ; +} diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index f515727..9ac8725 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -90,6 +90,7 @@ config PLATFORM_AT32AP select ARCH_REQUIRE_GPIOLIB select GENERIC_ALLOCATOR select HAVE_FB_ATMEL + select HAVE_NET_MACB # # CPU types diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index 98f94d0..a727f54 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c @@ -314,10 +314,9 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, vfree(module->arch.syminfo); module->arch.syminfo = NULL; - return module_bug_finalize(hdr, sechdrs, module); + return 0; } void module_arch_cleanup(struct module *module) { - module_bug_cleanup(module); } diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 0974c0e..bab0129 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -121,6 +121,9 @@ static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8) struct user_context *user = current->thread.user; unsigned long tbr, psr; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + tbr = user->i.tbr; psr = user->i.psr; if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context))) @@ -250,6 +253,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) struct sigframe __user *frame; int rsig; + set_fs(USER_DS); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) @@ -293,22 +298,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) (unsigned long) (frame->retcode + 2)); } - /* set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; - + /* Set up registers for the signal handler */ if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + struct fdpic_func_descriptor desc; + if (copy_from_user(&desc, funcptr, sizeof(desc))) + goto give_sigsegv; + __frame->pc = desc.text; + __frame->gr15 = desc.GOT; } else { __frame->pc = (unsigned long) ka->sa.sa_handler; __frame->gr15 = 0; } - set_fs(USER_DS); + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) @@ -323,7 +329,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } /* end setup_frame() */ @@ -338,6 +344,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; int rsig; + set_fs(USER_DS); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) @@ -392,22 +400,23 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; - __frame->gr9 = (unsigned long) &frame->info; - if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + struct fdpic_func_descriptor desc; + if (copy_from_user(&desc, funcptr, sizeof(desc))) + goto give_sigsegv; + __frame->pc = desc.text; + __frame->gr15 = desc.GOT; } else { __frame->pc = (unsigned long) ka->sa.sa_handler; __frame->gr15 = 0; } - set_fs(USER_DS); + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; + __frame->gr9 = (unsigned long) &frame->info; /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) @@ -422,7 +431,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } /* end setup_rt_frame() */ @@ -437,7 +446,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, int ret; /* Are we from a system call? */ - if (in_syscall(__frame)) { + if (__frame->syscallno != -1) { /* If so, check system call restarting.. */ switch (__frame->gr8) { case -ERESTART_RESTARTBLOCK: @@ -456,6 +465,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, __frame->gr8 = __frame->orig_gr8; __frame->pc -= 4; } + __frame->syscallno = -1; } /* Set up the stack frame */ @@ -538,10 +548,11 @@ no_signal: break; case -ERESTART_RESTARTBLOCK: - __frame->gr8 = __NR_restart_syscall; + __frame->gr7 = __NR_restart_syscall; __frame->pc -= 4; break; } + __frame->syscallno = -1; } /* if there's no signal to deliver, we just put the saved sigmask diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c index 0865e29..db4953d 100644 --- a/arch/h8300/kernel/module.c +++ b/arch/h8300/kernel/module.c @@ -112,10 +112,9 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - return module_bug_finalize(hdr, sechdrs, me); + return 0; } void module_arch_cleanup(struct module *mod) { - module_bug_cleanup(mod); } diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index f90edc8..9301a28 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h @@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) } static __inline__ void __user * -compat_alloc_user_space (long len) +arch_compat_alloc_user_space (long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 3567d54..331d42b 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -420,22 +420,31 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set ;; RSM_PSR_I(p0, r18, r19) // mask interrupt delivery - mov ar.ccv=0 andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP + mov r8=EINVAL // default to EINVAL #ifdef CONFIG_SMP - mov r17=1 + // __ticket_spin_trylock(r31) + ld4 r17=[r31] ;; - cmpxchg4.acq r18=[r31],r17,ar.ccv // try to acquire the lock - mov r8=EINVAL // default to EINVAL + mov.m ar.ccv=r17 + extr.u r9=r17,17,15 + adds r19=1,r17 + extr.u r18=r17,0,15 + ;; + cmp.eq p6,p7=r9,r18 ;; +(p6) cmpxchg4.acq r9=[r31],r19,ar.ccv +(p6) dep.z r20=r19,1,15 // next serving ticket for unlock +(p7) br.cond.spnt.many .lock_contention + ;; + cmp4.eq p0,p7=r9,r17 + adds r31=2,r31 +(p7) br.cond.spnt.many .lock_contention ld8 r3=[r2] // re-read current->blocked now that we hold the lock - cmp4.ne p6,p0=r18,r0 -(p6) br.cond.spnt.many .lock_contention ;; #else ld8 r3=[r2] // re-read current->blocked now that we hold the lock - mov r8=EINVAL // default to EINVAL #endif add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16 add r19=IA64_TASK_SIGNAL_OFFSET,r16 @@ -490,7 +499,9 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set (p6) br.cond.spnt.few 1b // yes -> retry #ifdef CONFIG_SMP - st4.rel [r31]=r0 // release the lock + // __ticket_spin_unlock(r31) + st2.rel [r31]=r20 + mov r20=0 // i must not leak kernel bits... #endif SSM_PSR_I(p0, p9, r31) ;; @@ -512,7 +523,8 @@ EX(.fail_efault, (p15) st8 [r34]=r3) .sig_pending: #ifdef CONFIG_SMP - st4.rel [r31]=r0 // release the lock + // __ticket_spin_unlock(r31) + st2.rel [r31]=r20 // release the lock #endif SSM_PSR_I(p0, p9, r17) ;; diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h index 9c1acb2..b2eeb0d 100644 --- a/arch/m32r/include/asm/signal.h +++ b/arch/m32r/include/asm/signal.h @@ -157,7 +157,6 @@ typedef struct sigaltstack { #undef __HAVE_ARCH_SIG_BITOPS struct pt_regs; -extern int do_signal(struct pt_regs *regs, sigset_t *oldset); #define ptrace_signal_deliver(regs, cookie) do { } while (0) diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h index 7612577..c705456 100644 --- a/arch/m32r/include/asm/unistd.h +++ b/arch/m32r/include/asm/unistd.h @@ -351,6 +351,7 @@ #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/ #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __IGNORE_lchown #define __IGNORE_setuid diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 4038698..225412b 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -235,10 +235,9 @@ work_resched: work_notifysig: ; deal with pending signals and ; notify-resume requests mv r0, sp ; arg1 : struct pt_regs *regs - ldi r1, #0 ; arg2 : sigset_t *oldset - mv r2, r9 ; arg3 : __u32 thread_info_flags + mv r1, r9 ; arg2 : __u32 thread_info_flags bl do_notify_resume - bra restore_all + bra resume_userspace ; perform syscall exit tracing ALIGN diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index e555091..0021ade 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -592,16 +592,17 @@ void user_enable_single_step(struct task_struct *child) if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) != sizeof(insn)) - break; + return -EIO; compute_next_pc(insn, pc, &next_pc, child); if (next_pc & 0x80000000) - break; + return -EIO; if (embed_debug_trap(child, next_pc)) - break; + return -EIO; invalidate_cache(); + return 0; } void user_disable_single_step(struct task_struct *child) diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index 144b0f1..7bbe386 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c @@ -28,37 +28,6 @@ #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -int do_signal(struct pt_regs *, sigset_t *); - -asmlinkage int -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, - unsigned long r2, unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, struct pt_regs *regs) -{ - sigset_t newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); - - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r2, unsigned long r3, unsigned long r4, @@ -218,7 +187,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) return (void __user *)((sp - frame_size) & -8ul); } -static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; @@ -275,22 +244,34 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, current->comm, current->pid, frame, regs->pc); #endif - return; + return 0; give_sigsegv: force_sigsegv(sig, current); + return -EFAULT; +} + +static int prev_insn(struct pt_regs *regs) +{ + u16 inst; + if (get_user(&inst, (u16 __user *)(regs->bpc - 2))) + return -EFAULT; + if ((inst & 0xfff0) == 0x10f0) /* trap ? */ + regs->bpc -= 2; + else + regs->bpc -= 4; + regs->syscall_nr = -1; + return 0; } /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - unsigned short inst; - /* Are we from a system call? */ if (regs->syscall_nr >= 0) { /* If so, check system call restarting.. */ @@ -308,16 +289,14 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, /* fallthrough */ case -ERESTARTNOINTR: regs->r0 = regs->orig_r0; - inst = *(unsigned short *)(regs->bpc - 2); - if ((inst & 0xfff0) == 0x10f0) /* trap ? */ - regs->bpc -= 2; - else - regs->bpc -= 4; + if (prev_insn(regs) < 0) + return -EFAULT; } } /* Set up the stack frame */ - setup_rt_frame(sig, ka, info, oldset, regs); + if (setup_rt_frame(sig, ka, info, oldset, regs)) + return -EFAULT; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -325,6 +304,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + return 0; } /* @@ -332,12 +312,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +static void do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; - unsigned short inst; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -346,12 +326,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) * if so. */ if (!user_mode(regs)) - return 1; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -363,8 +345,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) */ /* Whee! Actually deliver the signal. */ - handle_signal(signr, &ka, &info, oldset, regs); - return 1; + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + return; } no_signal: @@ -375,31 +359,24 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) regs->r0 == -ERESTARTSYS || regs->r0 == -ERESTARTNOINTR) { regs->r0 = regs->orig_r0; - inst = *(unsigned short *)(regs->bpc - 2); - if ((inst & 0xfff0) == 0x10f0) /* trap ? */ - regs->bpc -= 2; - else - regs->bpc -= 4; - } - if (regs->r0 == -ERESTART_RESTARTBLOCK){ + prev_insn(regs); + } else if (regs->r0 == -ERESTART_RESTARTBLOCK){ regs->r0 = regs->orig_r0; regs->r7 = __NR_restart_syscall; - inst = *(unsigned short *)(regs->bpc - 2); - if ((inst & 0xfff0) == 0x10f0) /* trap ? */ - regs->bpc -= 2; - else - regs->bpc -= 4; + prev_insn(regs); } } - return 0; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* * notification of userspace execution resumption * - triggered by current->work.notify_resume */ -void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, - __u32 thread_info_flags) +void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags) { /* Pending single-step? */ if (thread_info_flags & _TIF_SINGLESTEP) @@ -407,7 +384,7 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs,oldset); + do_signal(regs); if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 60b15d0..b43b36b 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -340,10 +340,13 @@ #define __NR_set_thread_area 334 #define __NR_atomic_cmpxchg_32 335 #define __NR_atomic_barrier 336 +#define __NR_fanotify_init 337 +#define __NR_fanotify_mark 338 +#define __NR_prlimit64 339 #ifdef __KERNEL__ -#define NR_syscalls 337 +#define NR_syscalls 340 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 2391bdf..6360c43 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -765,4 +765,7 @@ sys_call_table: .long sys_set_thread_area .long sys_atomic_cmpxchg_32 /* 335 */ .long sys_atomic_barrier + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c index 8f06408..05285d0 100644 --- a/arch/m68k/mac/macboing.c +++ b/arch/m68k/mac/macboing.c @@ -162,7 +162,7 @@ static void mac_init_asc( void ) void mac_mksound( unsigned int freq, unsigned int length ) { __u32 cfreq = ( freq << 5 ) / 468; - __u32 flags; + unsigned long flags; int i; if ( mac_special_bell == NULL ) @@ -224,7 +224,7 @@ static void mac_nosound( unsigned long ignored ) */ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume ) { - __u32 flags; + unsigned long flags; /* if the bell is already ringing, ring longer */ if ( mac_bell_duration > 0 ) @@ -271,7 +271,7 @@ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsig static void mac_quadra_ring_bell( unsigned long ignored ) { int i, count = mac_asc_samplespersec / HZ; - __u32 flags; + unsigned long flags; /* * we neither want a sound buffer overflow nor underflow, so we need to match diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index b30b3eb..79b1ed1 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S @@ -355,6 +355,9 @@ ENTRY(sys_call_table) .long sys_set_thread_area .long sys_atomic_cmpxchg_32 /* 335 */ .long sys_atomic_barrier + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 3ad59dd..5526faa 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -13,6 +13,7 @@ config MIPS select HAVE_KPROBES select HAVE_KRETPROBES select RTC_LIB if !MACH_LOONGSON + select GENERIC_ATOMIC64 if !64BIT mainmenu "Linux/MIPS Kernel Configuration" @@ -1646,8 +1647,16 @@ config MIPS_MT_SMP select SYS_SUPPORTS_SMP select SMP_UP help - This is a kernel model which is also known a VSMP or lately - has been marketesed into SMVP. + This is a kernel model which is known a VSMP but lately has been + marketesed into SMVP. + Virtual SMP uses the processor's VPEs to implement virtual + processors. In currently available configuration of the 34K processor + this allows for a dual processor. Both processors will share the same + primary caches; each will obtain the half of the TLB for it's own + exclusive use. For a layman this model can be described as similar to + what Intel calls Hyperthreading. + + For further information see http://www.linux-mips.org/wiki/34K#VSMP config MIPS_MT_SMTC bool "SMTC: Use all TCs on all VPEs for SMP" @@ -1664,6 +1673,14 @@ config MIPS_MT_SMTC help This is a kernel model which is known a SMTC or lately has been marketesed into SMVP. + is presenting the available TC's of the core as processors to Linux. + On currently available 34K processors this means a Linux system will + see up to 5 processors. The implementation of the SMTC kernel differs + significantly from VSMP and cannot efficiently coexist in the same + kernel binary so the choice between VSMP and SMTC is a compile time + decision. + + For further information see http://www.linux-mips.org/wiki/34K#SMTC endchoice diff --git a/arch/mips/alchemy/common/prom.c b/arch/mips/alchemy/common/prom.c index c29511b..5340210 100644 --- a/arch/mips/alchemy/common/prom.c +++ b/arch/mips/alchemy/common/prom.c @@ -43,7 +43,7 @@ int prom_argc; char **prom_argv; char **prom_envp; -void prom_init_cmdline(void) +void __init prom_init_cmdline(void) { int i; @@ -104,7 +104,7 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str) } } -int prom_get_ethernet_addr(char *ethernet_addr) +int __init prom_get_ethernet_addr(char *ethernet_addr) { char *ethaddr_str; @@ -123,7 +123,6 @@ int prom_get_ethernet_addr(char *ethernet_addr) return 0; } -EXPORT_SYMBOL(prom_get_ethernet_addr); void __init prom_free_prom_memory(void) { diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index ed9bb70..5fd7f7a 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -59,7 +59,7 @@ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE hostprogs-y := calc_vmlinuz_load_addr VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \ - $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS)) + $(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS)) vmlinuzobjs-y += $(obj)/piggy.o diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig index 094c17e..47323ca 100644 --- a/arch/mips/cavium-octeon/Kconfig +++ b/arch/mips/cavium-octeon/Kconfig @@ -83,3 +83,7 @@ config ARCH_SPARSEMEM_ENABLE def_bool y select SPARSEMEM_STATIC depends on CPU_CAVIUM_OCTEON + +config CAVIUM_OCTEON_HELPER + def_bool y + depends on OCTEON_ETHERNET || PCI diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c index c664c8c..a5b4279 100644 --- a/arch/mips/cavium-octeon/cpu.c +++ b/arch/mips/cavium-octeon/cpu.c @@ -41,7 +41,7 @@ static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action, return NOTIFY_OK; /* Let default notifier send signals */ } -static int cnmips_cu2_setup(void) +static int __init cnmips_cu2_setup(void) { return cu2_notifier(cnmips_cu2_call, 0); } diff --git a/arch/mips/cavium-octeon/executive/Makefile b/arch/mips/cavium-octeon/executive/Makefile index 2fd66db..7f41c5b 100644 --- a/arch/mips/cavium-octeon/executive/Makefile +++ b/arch/mips/cavium-octeon/executive/Makefile @@ -11,4 +11,4 @@ obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o -obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-jtag.o +obj-$(CONFIG_CAVIUM_OCTEON_HELPER) += cvmx-helper-errata.o cvmx-helper-jtag.o diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index c63c56b..47d87da 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -782,6 +782,10 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) */ #define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0) +#else /* !CONFIG_64BIT */ + +#include <asm-generic/atomic64.h> + #endif /* CONFIG_64BIT */ /* diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 613f691..dbc5106 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = (struct pt_regs *) ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h index 2cb2f0c..3532e2c 100644 --- a/arch/mips/include/asm/cop2.h +++ b/arch/mips/include/asm/cop2.h @@ -24,7 +24,7 @@ extern int cu2_notifier_call_chain(unsigned long val, void *v); #define cu2_notifier(fn, pri) \ ({ \ - static struct notifier_block fn##_nb __cpuinitdata = { \ + static struct notifier_block fn##_nb = { \ .notifier_call = fn, \ .priority = pri \ }; \ diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 9b9436a..86548da 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -321,6 +321,7 @@ struct gic_intrmask_regs { */ struct gic_intr_map { unsigned int cpunum; /* Directed to this CPU */ +#define GIC_UNUSED 0xdead /* Dummy data */ unsigned int pin; /* Directed to this Pin */ unsigned int polarity; /* Polarity : +/- */ unsigned int trigtype; /* Trigger : Edge/Levl */ diff --git a/arch/mips/include/asm/mach-tx49xx/kmalloc.h b/arch/mips/include/asm/mach-tx49xx/kmalloc.h index b74caf6..ff9a8b8 100644 --- a/arch/mips/include/asm/mach-tx49xx/kmalloc.h +++ b/arch/mips/include/asm/mach-tx49xx/kmalloc.h @@ -1,6 +1,6 @@ #ifndef __ASM_MACH_TX49XX_KMALLOC_H #define __ASM_MACH_TX49XX_KMALLOC_H -#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES #endif /* __ASM_MACH_TX49XX_KMALLOC_H */ diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h index cea872f..d11aa02 100644 --- a/arch/mips/include/asm/mips-boards/maltaint.h +++ b/arch/mips/include/asm/mips-boards/maltaint.h @@ -88,9 +88,6 @@ #define GIC_EXT_INTR(x) x -/* Dummy data */ -#define X 0xdead - /* External Interrupts used for IPI */ #define GIC_IPI_EXT_INTR_RESCHED_VPE0 16 #define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17 diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index a16beaf..e59cd1a 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -150,6 +150,20 @@ typedef struct { unsigned long pgprot; } pgprot_t; ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) #endif #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) + +/* + * RELOC_HIDE was originally added by 6007b903dfe5f1d13e0c711ac2894bdd4a61b1ad + * (lmo) rsp. 8431fd094d625b94d364fe393076ccef88e6ce18 (kernel.org). The + * discussion can be found in lkml posting + * <a2ebde260608230500o3407b108hc03debb9da6e62c@mail.gmail.com> which is + * archived at http://lists.linuxcoding.com/kernel/2006-q3/msg17360.html + * + * It is unclear if the misscompilations mentioned in + * http://lkml.org/lkml/2010/8/8/138 also affect MIPS so we keep this one + * until GCC 3.x has been retired before we can apply + * https://patchwork.linux-mips.org/patch/1541/ + */ + #define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0)) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) diff --git a/arch/mips/include/asm/siginfo.h b/arch/mips/include/asm/siginfo.h index 96e28f1..1ca64b4 100644 --- a/arch/mips/include/asm/siginfo.h +++ b/arch/mips/include/asm/siginfo.h @@ -88,6 +88,7 @@ typedef struct siginfo { #ifdef __ARCH_SI_TRAPNO int _trapno; /* TRAP # which caused the signal */ #endif + short _addr_lsb; } _sigfault; /* SIGPOLL, SIGXFSZ (To do ...) */ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 2376f2e..70df9c0 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -146,7 +146,8 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH) /* work to do on interrupt/exception return */ -#define _TIF_WORK_MASK (0x0000ffef & ~_TIF_SECCOMP) +#define _TIF_WORK_MASK (0x0000ffef & \ + ~(_TIF_SECCOMP | _TIF_SYSCALL_AUDIT)) /* work to do on any return to u-space */ #define _TIF_ALLWORK_MASK (0x8000ffff & ~_TIF_SECCOMP) diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index baa318a..550725b 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -356,16 +356,19 @@ #define __NR_perf_event_open (__NR_Linux + 333) #define __NR_accept4 (__NR_Linux + 334) #define __NR_recvmmsg (__NR_Linux + 335) +#define __NR_fanotify_init (__NR_Linux + 336) +#define __NR_fanotify_mark (__NR_Linux + 337) +#define __NR_prlimit64 (__NR_Linux + 338) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 335 +#define __NR_Linux_syscalls 338 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 335 +#define __NR_O32_Linux_syscalls 338 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -668,16 +671,19 @@ #define __NR_perf_event_open (__NR_Linux + 292) #define __NR_accept4 (__NR_Linux + 293) #define __NR_recvmmsg (__NR_Linux + 294) +#define __NR_fanotify_init (__NR_Linux + 295) +#define __NR_fanotify_mark (__NR_Linux + 296) +#define __NR_prlimit64 (__NR_Linux + 297) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 294 +#define __NR_Linux_syscalls 297 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 294 +#define __NR_64_Linux_syscalls 297 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -985,16 +991,19 @@ #define __NR_accept4 (__NR_Linux + 297) #define __NR_recvmmsg (__NR_Linux + 298) #define __NR_getdents64 (__NR_Linux + 299) +#define __NR_fanotify_init (__NR_Linux + 300) +#define __NR_fanotify_mark (__NR_Linux + 301) +#define __NR_prlimit64 (__NR_Linux + 302) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 299 +#define __NR_Linux_syscalls 302 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 299 +#define __NR_N32_Linux_syscalls 302 #ifdef __KERNEL__ diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index b181f2f..82ba9f6 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -7,7 +7,6 @@ #include <asm/io.h> #include <asm/gic.h> #include <asm/gcmpregs.h> -#include <asm/mips-boards/maltaint.h> #include <asm/irq.h> #include <linux/hardirq.h> #include <asm-generic/bitops/find.h> @@ -131,7 +130,7 @@ static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask) int i; irq -= _irqbase; - pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq); + pr_debug("%s(%d) called\n", __func__, irq); cpumask_and(&tmp, cpumask, cpu_online_mask); if (cpus_empty(tmp)) return -1; @@ -222,7 +221,7 @@ static void __init gic_basic_init(int numintrs, int numvpes, /* Setup specifics */ for (i = 0; i < mapsize; i++) { cpu = intrmap[i].cpunum; - if (cpu == X) + if (cpu == GIC_UNUSED) continue; if (cpu == 0 && i != 0 && intrmap[i].flags == 0) continue; diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 1f4e2fa..f4546e9 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -283,7 +283,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, struct pt_regs *regs = args->regs; int trap = (regs->cp0_cause & 0x7c) >> 2; - /* Userpace events, ignore. */ + /* Userspace events, ignore. */ if (user_mode(regs)) return NOTIFY_DONE; diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 80e2ba6..29811f0 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -251,7 +251,7 @@ void sp_work_handle_request(void) memset(&tz, 0, sizeof(tz)); if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv, (int)&tz, 0, 0)) == 0) - ret.retval = tv.tv_sec; + ret.retval = tv.tv_sec; break; case MTSP_SYSCALL_EXIT: diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index c2dab14..6343b4a 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -341,3 +341,10 @@ asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf, { return sys_lookup_dcookie(merge_64(a0, a1), buf, len); } + +SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags, + u64, a3, u64, a4, int, dfd, const char __user *, pathname) +{ + return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4), + dfd, pathname); +} diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 17202bb..584415e 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -583,7 +583,10 @@ einval: li v0, -ENOSYS sys sys_rt_tgsigqueueinfo 4 sys sys_perf_event_open 5 sys sys_accept4 4 - sys sys_recvmmsg 5 + sys sys_recvmmsg 5 /* 4335 */ + sys sys_fanotify_init 2 + sys sys_fanotify_mark 6 + sys sys_prlimit64 4 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index a8a6c59..5573f8e 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -416,9 +416,12 @@ sys_call_table: PTR sys_pipe2 PTR sys_inotify_init1 PTR sys_preadv - PTR sys_pwritev /* 5390 */ + PTR sys_pwritev /* 5290 */ PTR sys_rt_tgsigqueueinfo PTR sys_perf_event_open PTR sys_accept4 - PTR sys_recvmmsg + PTR sys_recvmmsg + PTR sys_fanotify_init /* 5295 */ + PTR sys_fanotify_mark + PTR sys_prlimit64 .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index a3d6613..1e38ec9 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -419,5 +419,8 @@ EXPORT(sysn32_call_table) PTR sys_perf_event_open PTR sys_accept4 PTR compat_sys_recvmmsg - PTR sys_getdents + PTR sys_getdents64 + PTR sys_fanotify_init /* 6300 */ + PTR sys_fanotify_mark + PTR sys_prlimit64 .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 813689e..171979f 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -538,5 +538,8 @@ sys_call_table: PTR compat_sys_rt_tgsigqueueinfo PTR sys_perf_event_open PTR sys_accept4 - PTR compat_sys_recvmmsg + PTR compat_sys_recvmmsg /* 4335 */ + PTR sys_fanotify_init + PTR sys_32_fanotify_mark + PTR sys_prlimit64 .size sys_call_table,.-sys_call_table diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 7ba8908..469d401 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -44,27 +44,39 @@ static inline int cpu_is_noncoherent_r10000(struct device *dev) static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) { + gfp_t dma_flag; + /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); -#ifdef CONFIG_ZONE_DMA +#ifdef CONFIG_ISA if (dev == NULL) - gfp |= __GFP_DMA; - else if (dev->coherent_dma_mask < DMA_BIT_MASK(24)) - gfp |= __GFP_DMA; + dma_flag = __GFP_DMA; else #endif -#ifdef CONFIG_ZONE_DMA32 +#if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA) if (dev->coherent_dma_mask < DMA_BIT_MASK(32)) - gfp |= __GFP_DMA32; + dma_flag = __GFP_DMA; + else if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) + dma_flag = __GFP_DMA32; + else +#endif +#if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA) + if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) + dma_flag = __GFP_DMA32; + else +#endif +#if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32) + if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) + dma_flag = __GFP_DMA; else #endif - ; + dma_flag = 0; /* Don't invoke OOM killer */ gfp |= __GFP_NORETRY; - return gfp; + return gfp | dma_flag; } void *dma_alloc_noncoherent(struct device *dev, size_t size, diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index 1ef75cd..274af3b 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -30,7 +30,7 @@ #define tc_lsize 32 extern unsigned long icache_way_size, dcache_way_size; -unsigned long tcache_size; +static unsigned long tcache_size; #include <asm/r4kcache.h> diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 15949b0..b79b24a 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -385,6 +385,8 @@ static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); */ #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK +#define X GIC_UNUSED + static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { { X, X, X, X, 0 }, { X, X, X, X, 0 }, @@ -404,6 +406,7 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { { X, X, X, X, 0 }, /* The remainder of this table is initialised by fill_ipi_map */ }; +#undef X /* * GCMP needs to be detected before any SMP initialisation diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c index 71f7d27..f31218e 100644 --- a/arch/mips/pci/pci-rc32434.c +++ b/arch/mips/pci/pci-rc32434.c @@ -118,7 +118,7 @@ static int __init rc32434_pcibridge_init(void) if (!((pcicvalue == PCIM_H_EA) || (pcicvalue == PCIM_H_IA_FIX) || (pcicvalue == PCIM_H_IA_RR))) { - pr_err(KERN_ERR "PCI init error!!!\n"); + pr_err("PCI init error!!!\n"); /* Not in Host Mode, return ERROR */ return -1; } diff --git a/arch/mips/pnx8550/common/reset.c b/arch/mips/pnx8550/common/reset.c index fadd8744..e7a12ff 100644 --- a/arch/mips/pnx8550/common/reset.c +++ b/arch/mips/pnx8550/common/reset.c @@ -22,29 +22,19 @@ */ #include <linux/kernel.h> +#include <asm/processor.h> #include <asm/reboot.h> #include <glb.h> void pnx8550_machine_restart(char *command) { - char head[] = "************* Machine restart *************"; - char foot[] = "*******************************************"; - - printk("\n\n"); - printk("%s\n", head); - if (command != NULL) - printk("* %s\n", command); - printk("%s\n", foot); - PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST; } void pnx8550_machine_halt(void) { - printk("*** Machine halt. (Not implemented) ***\n"); -} - -void pnx8550_machine_power_off(void) -{ - printk("*** Machine power off. (Not implemented) ***\n"); + while (1) { + if (cpu_wait) + cpu_wait(); + } } diff --git a/arch/mips/pnx8550/common/setup.c b/arch/mips/pnx8550/common/setup.c index 64246c9..43cb394 100644 --- a/arch/mips/pnx8550/common/setup.c +++ b/arch/mips/pnx8550/common/setup.c @@ -44,7 +44,6 @@ extern void __init board_setup(void); extern void pnx8550_machine_restart(char *); extern void pnx8550_machine_halt(void); -extern void pnx8550_machine_power_off(void); extern struct resource ioport_resource; extern struct resource iomem_resource; extern char *prom_getcmdline(void); @@ -100,7 +99,7 @@ void __init plat_mem_setup(void) _machine_restart = pnx8550_machine_restart; _machine_halt = pnx8550_machine_halt; - pm_power_off = pnx8550_machine_power_off; + pm_power_off = pnx8550_machine_halt; /* Clear the Global 2 Register, PCI Inta Output Enable Registers Bit 1:Enable DAC Powerdown diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 444b9f9..7c2a2f7 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -8,7 +8,6 @@ mainmenu "Linux Kernel Configuration" config MN10300 def_bool y select HAVE_OPROFILE - select HAVE_ARCH_TRACEHOOK config AM33 def_bool y diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug index ff80e86..ce83c74 100644 --- a/arch/mn10300/Kconfig.debug +++ b/arch/mn10300/Kconfig.debug @@ -101,7 +101,7 @@ config GDBSTUB_DEBUG_BREAKPOINT choice prompt "GDB stub port" - default GDBSTUB_TTYSM0 + default GDBSTUB_ON_TTYSM0 depends on GDBSTUB help Select the serial port used for GDB-stub. diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h index f49ac49..3f50e96 100644 --- a/arch/mn10300/include/asm/bitops.h +++ b/arch/mn10300/include/asm/bitops.h @@ -229,9 +229,9 @@ int ffs(int x) #include <asm-generic/bitops/hweight.h> #define ext2_set_bit_atomic(lock, nr, addr) \ - test_and_set_bit((nr) ^ 0x18, (addr)) + test_and_set_bit((nr), (addr)) #define ext2_clear_bit_atomic(lock, nr, addr) \ - test_and_clear_bit((nr) ^ 0x18, (addr)) + test_and_clear_bit((nr), (addr)) #include <asm-generic/bitops/ext2-non-atomic.h> #include <asm-generic/bitops/minix-le.h> diff --git a/arch/mn10300/include/asm/signal.h b/arch/mn10300/include/asm/signal.h index 7e891fc..1865d72 100644 --- a/arch/mn10300/include/asm/signal.h +++ b/arch/mn10300/include/asm/signal.h @@ -78,7 +78,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 9d49073..db509dd 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c @@ -156,17 +156,17 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { ._intr = &SC0ICR, ._rxb = &SC0RXB, ._txb = &SC0TXB, - .rx_name = "ttySM0/Rx", - .tx_name = "ttySM0/Tx", + .rx_name = "ttySM0:Rx", + .tx_name = "ttySM0:Tx", #ifdef CONFIG_MN10300_TTYSM0_TIMER8 - .tm_name = "ttySM0/Timer8", + .tm_name = "ttySM0:Timer8", ._tmxmd = &TM8MD, ._tmxbr = &TM8BR, ._tmicr = &TM8ICR, .tm_irq = TM8IRQ, .div_timer = MNSCx_DIV_TIMER_16BIT, #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ - .tm_name = "ttySM0/Timer2", + .tm_name = "ttySM0:Timer2", ._tmxmd = &TM2MD, ._tmxbr = (volatile u16 *) &TM2BR, ._tmicr = &TM2ICR, @@ -209,17 +209,17 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { ._intr = &SC1ICR, ._rxb = &SC1RXB, ._txb = &SC1TXB, - .rx_name = "ttySM1/Rx", - .tx_name = "ttySM1/Tx", + .rx_name = "ttySM1:Rx", + .tx_name = "ttySM1:Tx", #ifdef CONFIG_MN10300_TTYSM1_TIMER9 - .tm_name = "ttySM1/Timer9", + .tm_name = "ttySM1:Timer9", ._tmxmd = &TM9MD, ._tmxbr = &TM9BR, ._tmicr = &TM9ICR, .tm_irq = TM9IRQ, .div_timer = MNSCx_DIV_TIMER_16BIT, #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ - .tm_name = "ttySM1/Timer3", + .tm_name = "ttySM1:Timer3", ._tmxmd = &TM3MD, ._tmxbr = (volatile u16 *) &TM3BR, ._tmicr = &TM3ICR, @@ -260,9 +260,9 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { .uart.lock = __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), .name = "ttySM2", - .rx_name = "ttySM2/Rx", - .tx_name = "ttySM2/Tx", - .tm_name = "ttySM2/Timer10", + .rx_name = "ttySM2:Rx", + .tx_name = "ttySM2:Tx", + .tm_name = "ttySM2:Timer10", ._iobase = &SC2CTR, ._control = &SC2CTR, ._status = &SC2STR, diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c index 6aea7fd..196a111 100644 --- a/arch/mn10300/kernel/module.c +++ b/arch/mn10300/kernel/module.c @@ -206,7 +206,7 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - return module_bug_finalize(hdr, sechdrs, me); + return 0; } /* @@ -214,5 +214,4 @@ int module_finalize(const Elf_Ehdr *hdr, */ void module_arch_cleanup(struct module *mod) { - module_bug_cleanup(mod); } diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 717db14..d4de05a 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c @@ -65,10 +65,10 @@ asmlinkage long sys_sigaction(int sig, old_sigset_t mask; if (verify_area(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } @@ -77,10 +77,10 @@ asmlinkage long sys_sigaction(int sig, if (!ret && oact) { if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; @@ -102,6 +102,9 @@ static int restore_sigcontext(struct pt_regs *regs, { unsigned int err = 0; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + if (is_using_fpu(current)) fpu_kill_state(current); @@ -330,8 +333,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, regs->d0 = sig; regs->d1 = (unsigned long) &frame->sc; - set_fs(USER_DS); - /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); @@ -345,7 +346,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } @@ -413,8 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->d0 = sig; regs->d1 = (long) &frame->info; - set_fs(USER_DS); - /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); @@ -428,10 +427,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } +static inline void stepback(struct pt_regs *regs) +{ + regs->pc -= 2; + regs->orig_d0 = -1; +} + /* * handle the actual delivery of a signal to userspace */ @@ -459,7 +464,7 @@ static int handle_signal(int sig, /* fallthrough */ case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; - regs->pc -= 2; + stepback(regs); } } @@ -527,12 +532,12 @@ static void do_signal(struct pt_regs *regs) case -ERESTARTSYS: case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; - regs->pc -= 2; + stepback(regs); break; case -ERESTART_RESTARTBLOCK: regs->d0 = __NR_restart_syscall; - regs->pc -= 2; + stepback(regs); break; } } diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile index 28b9d98..1557277 100644 --- a/arch/mn10300/mm/Makefile +++ b/arch/mn10300/mm/Makefile @@ -2,13 +2,11 @@ # Makefile for the MN10300-specific memory management code # +cacheflush-y := cache.o cache-mn10300.o +cacheflush-$(CONFIG_MN10300_CACHE_WBACK) += cache-flush-mn10300.o + +cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o + obj-y := \ init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \ - misalignment.o dma-alloc.o - -ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y) -obj-y += cache.o cache-mn10300.o -ifeq ($(CONFIG_MN10300_CACHE_WBACK),y) -obj-y += cache-flush-mn10300.o -endif -endif + misalignment.o dma-alloc.o $(cacheflush-y) diff --git a/arch/mn10300/mm/cache-disabled.c b/arch/mn10300/mm/cache-disabled.c new file mode 100644 index 0000000..f669ea4 --- /dev/null +++ b/arch/mn10300/mm/cache-disabled.c @@ -0,0 +1,21 @@ +/* Handle the cache being disabled + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include <linux/mm.h> + +/* + * allow userspace to flush the instruction cache + */ +asmlinkage long sys_cacheflush(unsigned long start, unsigned long end) +{ + if (end < start) + return -EINVAL; + return 0; +} diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c index 1b76719..9261217 100644 --- a/arch/mn10300/mm/cache.c +++ b/arch/mn10300/mm/cache.c @@ -54,13 +54,30 @@ EXPORT_SYMBOL(flush_icache_page); void flush_icache_range(unsigned long start, unsigned long end) { #ifdef CONFIG_MN10300_CACHE_WBACK - unsigned long addr, size, off; + unsigned long addr, size, base, off; struct page *page; pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *ppte, pte; + if (end > 0x80000000UL) { + /* addresses above 0xa0000000 do not go through the cache */ + if (end > 0xa0000000UL) { + end = 0xa0000000UL; + if (start >= end) + return; + } + + /* kernel addresses between 0x80000000 and 0x9fffffff do not + * require page tables, so we just map such addresses directly */ + base = (start >= 0x80000000UL) ? start : 0x80000000UL; + mn10300_dcache_flush_range(base, end); + if (base == start) + goto invalidate; + end = base; + } + for (; start < end; start += size) { /* work out how much of the page to flush */ off = start & (PAGE_SIZE - 1); @@ -104,6 +121,7 @@ void flush_icache_range(unsigned long start, unsigned long end) } #endif +invalidate: mn10300_icache_inv(); } EXPORT_SYMBOL(flush_icache_range); diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 02b77ba..efa0b60 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static __inline__ void __user *compat_alloc_user_space(long len) +static __inline__ void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = ¤t->thread.regs; return (void __user *)regs->gr[30]; diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 159a2b8..6e81bb5 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -941,11 +941,10 @@ int module_finalize(const Elf_Ehdr *hdr, nsyms = newptr - (Elf_Sym *)symhdr->sh_addr; DEBUGP("NEW num_symtab %lu\n", nsyms); symhdr->sh_size = nsyms * sizeof(Elf_Sym); - return module_bug_finalize(hdr, sechdrs, me); + return 0; } void module_arch_cleanup(struct module *mod) { deregister_unwind_table(mod); - module_bug_cleanup(mod); } diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 396d21a..a11d4ea 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = current->thread.regs; unsigned long usp = regs->gpr[1]; diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 477c663..49cee9d 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c @@ -63,11 +63,6 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { const Elf_Shdr *sect; - int err; - - err = module_bug_finalize(hdr, sechdrs, me); - if (err) - return err; /* Apply feature fixups */ sect = find_section(hdr, sechdrs, "__ftr_fixup"); @@ -101,5 +96,4 @@ int module_finalize(const Elf_Ehdr *hdr, void module_arch_cleanup(struct module *mod) { - module_bug_cleanup(mod); } diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 7109f5b..2300426 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -138,6 +138,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) ti->local_flags &= ~_TLF_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } + regs->trap = 0; return 0; /* no signals delivered */ } @@ -164,6 +165,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); } + regs->trap = 0; if (ret) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 2666101..b96a3a0 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -511,6 +511,7 @@ static long restore_user_regs(struct pt_regs *regs, if (!sig) save_r2 = (unsigned int)regs->gpr[2]; err = restore_general_regs(regs, sr); + regs->trap = 0; err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); if (!sig) regs->gpr[2] = (unsigned long) save_r2; @@ -884,7 +885,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, regs->nip = (unsigned long) ka->sa.sa_handler; /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; - regs->trap = 0; return 1; badframe: @@ -1228,7 +1228,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, regs->nip = (unsigned long) ka->sa.sa_handler; /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; - regs->trap = 0; return 1; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 2fe6fc6..27c4a45 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -178,7 +178,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, err |= __get_user(regs->xer, &sc->gp_regs[PT_XER]); err |= __get_user(regs->ccr, &sc->gp_regs[PT_CCR]); /* skip SOFTE */ - err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]); + regs->trap = 0; err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]); err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]); err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]); diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c index 5b243bd..3dc2a8d 100644 --- a/arch/powerpc/platforms/512x/clock.c +++ b/arch/powerpc/platforms/512x/clock.c @@ -57,7 +57,7 @@ static struct clk *mpc5121_clk_get(struct device *dev, const char *id) int id_match = 0; if (dev == NULL || id == NULL) - return NULL; + return clk; mutex_lock(&clocks_mutex); list_for_each_entry(p, &clocks, node) { diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 45c0cb9..18c1048 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -99,7 +99,7 @@ static void __init efika_pcisetup(void) if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING EFIKA_PLATFORM_NAME ": Can't get bus-range for %s\n", pcictrl->full_name); - return; + goto out_put; } if (bus_range[1] == bus_range[0]) @@ -111,12 +111,12 @@ static void __init efika_pcisetup(void) printk(" controlled by %s\n", pcictrl->full_name); printk("\n"); - hose = pcibios_alloc_controller(of_node_get(pcictrl)); + hose = pcibios_alloc_controller(pcictrl); if (!hose) { printk(KERN_WARNING EFIKA_PLATFORM_NAME ": Can't allocate PCI controller structure for %s\n", pcictrl->full_name); - return; + goto out_put; } hose->first_busno = bus_range[0]; @@ -124,6 +124,9 @@ static void __init efika_pcisetup(void) hose->ops = &rtas_pci_ops; pci_process_bridge_OF_ranges(hose, pcictrl, 0); + return; +out_put: + of_node_put(pcictrl); } #else diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 6e90531..41f3a7e 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -325,12 +325,16 @@ int mpc5200_psc_ac97_gpio_reset(int psc_number) clrbits32(&simple_gpio->simple_dvo, sync | out); clrbits8(&wkup_gpio->wkup_dvo, reset); - /* wait at lease 1 us */ - udelay(2); + /* wait for 1 us */ + udelay(1); /* Deassert reset */ setbits8(&wkup_gpio->wkup_dvo, reset); + /* wait at least 200ns */ + /* 7 ~= (200ns * timebase) / ns2sec */ + __delay(7); + /* Restore pin-muxing */ out_be32(&simple_gpio->port_config, mux); diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 104f200..a875c2f 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -181,7 +181,7 @@ static inline int is_compat_task(void) #endif -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { unsigned long stack; diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 22cfd63..f7167ee 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -407,10 +407,9 @@ int module_finalize(const Elf_Ehdr *hdr, { vfree(me->arch.syminfo); me->arch.syminfo = NULL; - return module_bug_finalize(hdr, sechdrs, me); + return 0; } void module_arch_cleanup(struct module *mod) { - module_bug_cleanup(mod); } diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index 43adddf..ae0be69 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c @@ -149,13 +149,11 @@ int module_finalize(const Elf_Ehdr *hdr, int ret = 0; ret |= module_dwarf_finalize(hdr, sechdrs, me); - ret |= module_bug_finalize(hdr, sechdrs, me); return ret; } void module_arch_cleanup(struct module *mod) { - module_bug_cleanup(mod); module_dwarf_cleanup(mod); } diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 5016f76..6f57325 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = current_thread_info()->kregs; unsigned long usp = regs->u_regs[UREG_I6]; diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 357ced3..6318e62 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1038,6 +1038,7 @@ static int __hw_perf_event_init(struct perf_event *event) if (atomic_read(&nmi_active) < 0) return -ENODEV; + pmap = NULL; if (attr->type == PERF_TYPE_HARDWARE) { if (attr->config >= sparc_pmu->max_events) return -EINVAL; @@ -1046,9 +1047,18 @@ static int __hw_perf_event_init(struct perf_event *event) pmap = sparc_map_cache_event(attr->config); if (IS_ERR(pmap)) return PTR_ERR(pmap); - } else + } else if (attr->type != PERF_TYPE_RAW) return -EOPNOTSUPP; + if (pmap) { + hwc->event_base = perf_event_encode(pmap); + } else { + /* User gives us "(encoding << 16) | pic_mask" for + * PERF_TYPE_RAW events. + */ + hwc->event_base = attr->config; + } + /* We save the enable bits in the config_base. */ hwc->config_base = sparc_pmu->irq_bit; if (!attr->exclude_user) @@ -1058,8 +1068,6 @@ static int __hw_perf_event_init(struct perf_event *event) if (!attr->exclude_hv) hwc->config_base |= sparc_pmu->hv_bit; - hwc->event_base = perf_event_encode(pmap); - n = 0; if (event->group_leader != event) { n = collect_events(event->group_leader, diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index ea22cd3..75fad42 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -453,8 +453,66 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) return err; } -static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +/* The I-cache flush instruction only works in the primary ASI, which + * right now is the nucleus, aka. kernel space. + * + * Therefore we have to kick the instructions out using the kernel + * side linear mapping of the physical address backing the user + * instructions. + */ +static void flush_signal_insns(unsigned long address) +{ + unsigned long pstate, paddr; + pte_t *ptep, pte; + pgd_t *pgdp; + pud_t *pudp; + pmd_t *pmdp; + + /* Commit all stores of the instructions we are about to flush. */ + wmb(); + + /* Disable cross-call reception. In this way even a very wide + * munmap() on another cpu can't tear down the page table + * hierarchy from underneath us, since that can't complete + * until the IPI tlb flush returns. + */ + + __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); + __asm__ __volatile__("wrpr %0, %1, %%pstate" + : : "r" (pstate), "i" (PSTATE_IE)); + + pgdp = pgd_offset(current->mm, address); + if (pgd_none(*pgdp)) + goto out_irqs_on; + pudp = pud_offset(pgdp, address); + if (pud_none(*pudp)) + goto out_irqs_on; + pmdp = pmd_offset(pudp, address); + if (pmd_none(*pmdp)) + goto out_irqs_on; + + ptep = pte_offset_map(pmdp, address); + pte = *ptep; + if (!pte_present(pte)) + goto out_unmap; + + paddr = (unsigned long) page_address(pte_page(pte)); + + __asm__ __volatile__("flush %0 + %1" + : /* no outputs */ + : "r" (paddr), + "r" (address & (PAGE_SIZE - 1)) + : "memory"); + +out_unmap: + pte_unmap(ptep); +out_irqs_on: + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); + +} + +static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { struct signal_frame32 __user *sf; int sigframe_size; @@ -547,13 +605,7 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (ka->ka_restorer) { regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; } else { - /* Flush instruction space. */ unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pud_t *pudp = pud_offset(pgdp, address); - pmd_t *pmdp = pmd_offset(pudp, address); - pte_t *ptep; - pte_t pte; regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); @@ -562,34 +614,22 @@ static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (err) goto sigsegv; - preempt_disable(); - ptep = pte_offset_map(pmdp, address); - pte = *ptep; - if (pte_present(pte)) { - unsigned long page = (unsigned long) - page_address(pte_page(pte)); - - wmb(); - __asm__ __volatile__("flush %0 + %1" - : /* no outputs */ - : "r" (page), - "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - pte_unmap(ptep); - preempt_enable(); + flush_signal_insns(address); } - return; + return 0; sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, - unsigned long signr, sigset_t *oldset, - siginfo_t *info) +static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, + unsigned long signr, sigset_t *oldset, + siginfo_t *info) { struct rt_signal_frame32 __user *sf; int sigframe_size; @@ -687,12 +727,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (ka->ka_restorer) regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; else { - /* Flush instruction space. */ unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pud_t *pudp = pud_offset(pgdp, address); - pmd_t *pmdp = pmd_offset(pudp, address); - pte_t *ptep; regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); @@ -704,38 +739,32 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, if (err) goto sigsegv; - preempt_disable(); - ptep = pte_offset_map(pmdp, address); - if (pte_present(*ptep)) { - unsigned long page = (unsigned long) - page_address(pte_page(*ptep)); - - wmb(); - __asm__ __volatile__("flush %0 + %1" - : /* no outputs */ - : "r" (page), - "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - pte_unmap(ptep); - preempt_enable(); + flush_signal_insns(address); } - return; + return 0; sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signr, current); + return -EFAULT; } -static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) +static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, + siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs) { + int err; + if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame32(ka, regs, signr, oldset, info); + err = setup_rt_frame32(ka, regs, signr, oldset, info); else - setup_frame32(ka, regs, signr, oldset); + err = setup_frame32(ka, regs, signr, oldset); + + if (err) + return err; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -743,6 +772,10 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, sigaddset(¤t->blocked,signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, @@ -789,16 +822,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, if (signr > 0) { if (restart_syscall) syscall_restart32(orig_i0, regs, &ka.sa); - handle_signal32(signr, &ka, &info, oldset, regs); - - /* A signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TS_RESTORE_SIGMASK flag. - */ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - - tracehook_signal_handler(signr, &info, &ka, regs, 0); + if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { + /* A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } return; } if (restart_syscall && @@ -809,12 +840,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } /* If there's no signal to deliver, we just put the saved sigmask diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 9882df9..5e5c5fd 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -315,8 +315,8 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) return err; } -static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { struct signal_frame __user *sf; int sigframe_size, err; @@ -384,16 +384,19 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } - return; + return 0; sigill_and_return: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset, siginfo_t *info) +static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame __user *sf; int sigframe_size; @@ -466,22 +469,30 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } - return; + return 0; sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static inline void +static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { + int err; + if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(ka, regs, signr, oldset, info); + err = setup_rt_frame(ka, regs, signr, oldset, info); else - setup_frame(ka, regs, signr, oldset); + err = setup_frame(ka, regs, signr, oldset); + + if (err) + return err; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -489,6 +500,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -546,17 +561,15 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, oldset, regs); - - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - tracehook_signal_handler(signr, &info, &ka, regs, 0); + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } return; } if (restart_syscall && @@ -567,12 +580,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) regs->u_regs[UREG_I0] = orig_i0; regs->pc -= 4; regs->npc -= 4; + pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->pc -= 4; regs->npc -= 4; + pt_regs_clear_syscall(regs); } /* if there's no signal to deliver, we just put the saved sigmask diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 9fa48c3..006fe45 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -409,7 +409,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * return (void __user *) sp; } -static inline void +static inline int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset, siginfo_t *info) { @@ -483,26 +483,37 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, } /* 4. return to kernel instructions */ regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - return; + return 0; sigill: do_exit(SIGILL); + return -EINVAL; + sigsegv: force_sigsegv(signo, current); + return -EFAULT; } -static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) +static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, + siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs) { - setup_rt_frame(ka, regs, signr, oldset, - (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); + int err; + + err = setup_rt_frame(ka, regs, signr, oldset, + (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); + if (err) + return err; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) sigaddset(¤t->blocked,signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -571,16 +582,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, oldset, regs); - - /* A signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TS_RESTORE_SIGMASK flag. - */ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - - tracehook_signal_handler(signr, &info, &ka, regs, 0); + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } return; } if (restart_syscall && @@ -591,12 +600,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; + pt_regs_clear_syscall(regs); } /* If there's no signal to deliver, we just put the saved sigmask diff --git a/arch/tile/include/arch/chip_tile64.h b/arch/tile/include/arch/chip_tile64.h index 1246573..261aaba 100644 --- a/arch/tile/include/arch/chip_tile64.h +++ b/arch/tile/include/arch/chip_tile64.h @@ -150,6 +150,9 @@ /** Is the PROC_STATUS SPR supported? */ #define CHIP_HAS_PROC_STATUS_SPR() 0 +/** Is the DSTREAM_PF SPR supported? */ +#define CHIP_HAS_DSTREAM_PF() 0 + /** Log of the number of mshims we have. */ #define CHIP_LOG_NUM_MSHIMS() 2 diff --git a/arch/tile/include/arch/chip_tilepro.h b/arch/tile/include/arch/chip_tilepro.h index e864c47..7001769 100644 --- a/arch/tile/include/arch/chip_tilepro.h +++ b/arch/tile/include/arch/chip_tilepro.h @@ -150,6 +150,9 @@ /** Is the PROC_STATUS SPR supported? */ #define CHIP_HAS_PROC_STATUS_SPR() 1 +/** Is the DSTREAM_PF SPR supported? */ +#define CHIP_HAS_DSTREAM_PF() 0 + /** Log of the number of mshims we have. */ #define CHIP_LOG_NUM_MSHIMS() 2 diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 5a34da6..8b60ec8 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h @@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr) return (long)(int)(long __force)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *)regs->sp - len; @@ -214,8 +214,9 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, struct compat_sigaction; struct compat_siginfo; struct compat_sigaltstack; -long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp); +long compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp); long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, struct compat_sigaction __user *oact, size_t sigsetsize); diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h index 8c95bef..ee43328 100644 --- a/arch/tile/include/asm/io.h +++ b/arch/tile/include/asm/io.h @@ -164,22 +164,22 @@ static inline void _tile_writeq(u64 val, unsigned long addr) #define iowrite32 writel #define iowrite64 writeq -static inline void *memcpy_fromio(void *dst, void *src, int len) +static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, + size_t len) { int x; BUG_ON((unsigned long)src & 0x3); for (x = 0; x < len; x += 4) *(u32 *)(dst + x) = readl(src + x); - return dst; } -static inline void *memcpy_toio(void *dst, void *src, int len) +static inline void memcpy_toio(volatile void __iomem *dst, const void *src, + size_t len) { int x; BUG_ON((unsigned long)dst & 0x3); for (x = 0; x < len; x += 4) writel(*(u32 *)(src + x), dst + x); - return dst; } /* diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index d942d09..ccd5f84 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h @@ -103,6 +103,18 @@ struct thread_struct { /* Any other miscellaneous processor state bits */ unsigned long proc_status; #endif +#if !CHIP_HAS_FIXED_INTVEC_BASE() + /* Interrupt base for PL0 interrupts */ + unsigned long interrupt_vector_base; +#endif +#if CHIP_HAS_TILE_RTF_HWM() + /* Tile cache retry fifo high-water mark */ + unsigned long tile_rtf_hwm; +#endif +#if CHIP_HAS_DSTREAM_PF() + /* Data stream prefetch control */ + unsigned long dstream_pf; +#endif #ifdef CONFIG_HARDWALL /* Is this task tied to an activated hardwall? */ struct hardwall_info *hardwall; diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h index acdae81..4a02bb0 100644 --- a/arch/tile/include/asm/ptrace.h +++ b/arch/tile/include/asm/ptrace.h @@ -51,10 +51,7 @@ typedef uint_reg_t pt_reg_t; /* * This struct defines the way the registers are stored on the stack during a - * system call/exception. It should be a multiple of 8 bytes to preserve - * normal stack alignment rules. - * - * Must track <sys/ucontext.h> and <sys/procfs.h> + * system call or exception. "struct sigcontext" has the same shape. */ struct pt_regs { /* Saved main processor registers; 56..63 are special. */ @@ -80,11 +77,6 @@ struct pt_regs { #endif /* __ASSEMBLY__ */ -/* Flag bits in pt_regs.flags */ -#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ -#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ -#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ - #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 @@ -101,6 +93,11 @@ struct pt_regs { #ifdef __KERNEL__ +/* Flag bits in pt_regs.flags */ +#define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ +#define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ +#define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ + #ifndef __ASSEMBLY__ #define instruction_pointer(regs) ((regs)->pc) diff --git a/arch/tile/include/asm/sigcontext.h b/arch/tile/include/asm/sigcontext.h index 7cd7672..5e2d033 100644 --- a/arch/tile/include/asm/sigcontext.h +++ b/arch/tile/include/asm/sigcontext.h @@ -15,13 +15,21 @@ #ifndef _ASM_TILE_SIGCONTEXT_H #define _ASM_TILE_SIGCONTEXT_H -/* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */ -#include <asm/ptrace.h> - -/* Must track <sys/ucontext.h> */ +#include <arch/abi.h> +/* + * struct sigcontext has the same shape as struct pt_regs, + * but is simplified since we know the fault is from userspace. + */ struct sigcontext { - struct pt_regs regs; + uint_reg_t gregs[53]; /* General-purpose registers. */ + uint_reg_t tp; /* Aliases gregs[TREG_TP]. */ + uint_reg_t sp; /* Aliases gregs[TREG_SP]. */ + uint_reg_t lr; /* Aliases gregs[TREG_LR]. */ + uint_reg_t pc; /* Program counter. */ + uint_reg_t ics; /* In Interrupt Critical Section? */ + uint_reg_t faultnum; /* Fault number. */ + uint_reg_t pad[5]; }; #endif /* _ASM_TILE_SIGCONTEXT_H */ diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index eb0253f..c1ee1d6 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h @@ -24,6 +24,7 @@ #include <asm-generic/signal.h> #if defined(__KERNEL__) && !defined(__ASSEMBLY__) +struct pt_regs; int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); void do_signal(struct pt_regs *regs); diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h index af165a7..ce99ffe 100644 --- a/arch/tile/include/asm/syscalls.h +++ b/arch/tile/include/asm/syscalls.h @@ -62,10 +62,12 @@ long sys_fork(void); long _sys_fork(struct pt_regs *regs); long sys_vfork(void); long _sys_vfork(struct pt_regs *regs); -long sys_execve(char __user *filename, char __user * __user *argv, - char __user * __user *envp); -long _sys_execve(char __user *filename, char __user * __user *argv, - char __user * __user *envp, struct pt_regs *regs); +long sys_execve(const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp); +long _sys_execve(const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp, struct pt_regs *regs); /* kernel/signal.c */ long sys_sigaltstack(const stack_t __user *, stack_t __user *); @@ -86,10 +88,13 @@ int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); #endif #ifdef CONFIG_COMPAT -long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp); -long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs *regs); +long compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp); +long _compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp, + struct pt_regs *regs); long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, struct compat_sigaltstack __user *uoss_ptr); long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 84f296c..8f58bdf 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -1506,13 +1506,6 @@ handle_ill: } STD_ENDPROC(handle_ill) - .pushsection .rodata, "a" - .align 8 -bpt_code: - bpt - ENDPROC(bpt_code) - .popsection - /* Various stub interrupt handlers and syscall handlers */ STD_ENTRY_LOCAL(_kernel_double_fault) diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 985cc28..84c2911 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -408,6 +408,15 @@ static void save_arch_state(struct thread_struct *t) #if CHIP_HAS_PROC_STATUS_SPR() t->proc_status = __insn_mfspr(SPR_PROC_STATUS); #endif +#if !CHIP_HAS_FIXED_INTVEC_BASE() + t->interrupt_vector_base = __insn_mfspr(SPR_INTERRUPT_VECTOR_BASE_0); +#endif +#if CHIP_HAS_TILE_RTF_HWM() + t->tile_rtf_hwm = __insn_mfspr(SPR_TILE_RTF_HWM); +#endif +#if CHIP_HAS_DSTREAM_PF() + t->dstream_pf = __insn_mfspr(SPR_DSTREAM_PF); +#endif } static void restore_arch_state(const struct thread_struct *t) @@ -428,14 +437,14 @@ static void restore_arch_state(const struct thread_struct *t) #if CHIP_HAS_PROC_STATUS_SPR() __insn_mtspr(SPR_PROC_STATUS, t->proc_status); #endif +#if !CHIP_HAS_FIXED_INTVEC_BASE() + __insn_mtspr(SPR_INTERRUPT_VECTOR_BASE_0, t->interrupt_vector_base); +#endif #if CHIP_HAS_TILE_RTF_HWM() - /* - * Clear this whenever we switch back to a process in case - * the previous process was monkeying with it. Even if enabled - * in CBOX_MSR1 via TILE_RTF_HWM_MIN, it's still just a - * performance hint, so isn't worth a full save/restore. - */ - __insn_mtspr(SPR_TILE_RTF_HWM, 0); + __insn_mtspr(SPR_TILE_RTF_HWM, t->tile_rtf_hwm); +#endif +#if CHIP_HAS_DSTREAM_PF() + __insn_mtspr(SPR_DSTREAM_PF, t->dstream_pf); #endif } @@ -561,8 +570,9 @@ out: } #ifdef CONFIG_COMPAT -long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs *regs) +long _compat_sys_execve(const char __user *path, + const compat_uptr_t __user *argv, + const compat_uptr_t __user *envp, struct pt_regs *regs) { long error; char *filename; @@ -657,7 +667,7 @@ void show_regs(struct pt_regs *regs) regs->regs[51], regs->regs[52], regs->tp); pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr); #else - for (i = 0; i < 52; i += 3) + for (i = 0; i < 52; i += 4) pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT " r%-2d: "REGFMT" r%-2d: "REGFMT"\n", i, regs->regs[i], i+1, regs->regs[i+1], diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 45b66a3..ce183aa 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c @@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; + /* + * Enforce that sigcontext is like pt_regs, and doesn't mess + * up our stack alignment rules. + */ + BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs)); + BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0); + for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) - err |= __get_user(((long *)regs)[i], - &((long __user *)(&sc->regs))[i]); + err |= __get_user(regs->regs[i], &sc->gregs[i]); regs->faultnum = INT_SWINT_1_SIGRETURN; - err |= __get_user(*pr0, &sc->regs.regs[0]); + err |= __get_user(*pr0, &sc->gregs[0]); return err; } @@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) int i, err = 0; for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) - err |= __put_user(((long *)regs)[i], - &((long __user *)(&sc->regs))[i]); + err |= __put_user(regs->regs[i], &sc->gregs[i]); return err; } @@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * Set up registers for signal handler. * Registers that we don't modify keep the value they had from * user-space at the time we took the signal. + * We always pass siginfo and mcontext, regardless of SA_SIGINFO, + * since some things rely on this (e.g. glibc's debug/segfault.c). */ regs->pc = (unsigned long) ka->sa.sa_handler; regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->sp = (unsigned long) frame; regs->lr = restorer; regs->regs[0] = (unsigned long) usig; - - if (ka->sa.sa_flags & SA_SIGINFO) { - /* Need extra arguments, so mark to restore caller-saves. */ - regs->regs[1] = (unsigned long) &frame->info; - regs->regs[2] = (unsigned long) &frame->uc; - regs->flags |= PT_FLAGS_CALLER_SAVES; - } + regs->regs[1] = (unsigned long) &frame->info; + regs->regs[2] = (unsigned long) &frame->uc; + regs->flags |= PT_FLAGS_CALLER_SAVES; /* * Notify any tracer that was single-stepping it. diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index 38a68b0b4..ea2e0ce 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c @@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt) pr_err(" <received signal %d>\n", frame->info.si_signo); } - return &frame->uc.uc_mcontext.regs; + return (struct pt_regs *)&frame->uc.uc_mcontext; } return NULL; } diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 2ab233b..47d0c37 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -255,18 +255,6 @@ static void uml_net_tx_timeout(struct net_device *dev) netif_wake_queue(dev); } -static int uml_net_set_mac(struct net_device *dev, void *addr) -{ - struct uml_net_private *lp = netdev_priv(dev); - struct sockaddr *hwaddr = addr; - - spin_lock_irq(&lp->lock); - eth_mac_addr(dev, hwaddr->sa_data); - spin_unlock_irq(&lp->lock); - - return 0; -} - static int uml_net_change_mtu(struct net_device *dev, int new_mtu) { dev->mtu = new_mtu; @@ -373,7 +361,7 @@ static const struct net_device_ops uml_netdev_ops = { .ndo_start_xmit = uml_net_start_xmit, .ndo_set_multicast_list = uml_net_set_multicast_list, .ndo_tx_timeout = uml_net_tx_timeout, - .ndo_set_mac_address = uml_net_set_mac, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = uml_net_change_mtu, .ndo_validate_addr = eth_validate_addr, }; @@ -472,7 +460,8 @@ static void eth_configure(int n, void *init, char *mac, ((*transport->user->init)(&lp->user, dev) != 0)) goto out_unregister; - eth_mac_addr(dev, device->mac); + /* don't use eth_mac_addr, it will not work here */ + memcpy(dev->dev_addr, device->mac, ETH_ALEN); dev->mtu = transport->user->mtu; dev->netdev_ops = ¨_netdev_ops; dev->ethtool_ops = ¨_net_ethtool_ops; diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index cd145ed..49b5e1e 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -62,7 +62,7 @@ static long execve1(const char *file, return error; } -long um_execve(const char *file, char __user *__user *argv, char __user *__user *env) +long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) { long err; @@ -72,8 +72,8 @@ long um_execve(const char *file, char __user *__user *argv, char __user *__user return err; } -long sys_execve(const char __user *file, char __user *__user *argv, - char __user *__user *env) +long sys_execve(const char __user *file, const char __user *const __user *argv, + const char __user *const __user *env) { long error; char *filename; diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h index 1303a10..5bf97db 100644 --- a/arch/um/kernel/internal.h +++ b/arch/um/kernel/internal.h @@ -1 +1 @@ -extern long um_execve(const char *file, char __user *__user *argv, char __user *__user *env); +extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env); diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 5ddb246..f958cb8 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -60,8 +60,8 @@ int kernel_execve(const char *filename, fs = get_fs(); set_fs(KERNEL_DS); - ret = um_execve(filename, (char __user *__user *)argv, - (char __user *__user *) envp); + ret = um_execve(filename, (const char __user *const __user *)argv, + (const char __user *const __user *) envp); set_fs(fs); return ret; diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 8aa1b59..e8c8881 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -74,7 +74,7 @@ endif ifdef CONFIG_CC_STACKPROTECTOR cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh - ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(biarch)),y) + ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y) stackp-y := -fstack-protector KBUILD_CFLAGS += $(stackp-y) else diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c index 030f4b9..5df2869 100644 --- a/arch/x86/boot/early_serial_console.c +++ b/arch/x86/boot/early_serial_console.c @@ -58,7 +58,19 @@ static void parse_earlyprintk(void) if (arg[pos] == ',') pos++; - if (!strncmp(arg, "ttyS", 4)) { + /* + * make sure we have + * "serial,0x3f8,115200" + * "serial,ttyS0,115200" + * "ttyS0,115200" + */ + if (pos == 7 && !strncmp(arg + pos, "0x", 2)) { + port = simple_strtoull(arg + pos, &e, 16); + if (port == 0 || arg + pos == e) + port = DEFAULT_SERIAL_PORT; + else + pos = e - arg; + } else if (!strncmp(arg + pos, "ttyS", 4)) { static const int bases[] = { 0x3f8, 0x2f8 }; int idx = 0; diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 0350311..2d93bdb 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -34,7 +34,7 @@ #include <asm/ia32.h> #undef WARN_OLD -#undef CORE_DUMP /* probably broken */ +#undef CORE_DUMP /* definitely broken */ static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs); static int load_aout_library(struct file *); @@ -131,21 +131,15 @@ static void set_brk(unsigned long start, unsigned long end) * macros to write out all the necessary info. */ -static int dump_write(struct file *file, const void *addr, int nr) -{ - return file->f_op->write(file, addr, nr, &file->f_pos) == nr; -} +#include <linux/coredump.h> #define DUMP_WRITE(addr, nr) \ if (!dump_write(file, (void *)(addr), (nr))) \ goto end_coredump; -#define DUMP_SEEK(offset) \ - if (file->f_op->llseek) { \ - if (file->f_op->llseek(file, (offset), 0) != (offset)) \ - goto end_coredump; \ - } else \ - file->f_pos = (offset) +#define DUMP_SEEK(offset) \ + if (!dump_seek(file, offset)) \ + goto end_coredump; #define START_DATA() (u.u_tsize << PAGE_SHIFT) #define START_STACK(u) (u.start_stack) @@ -217,12 +211,6 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, dump_size = dump.u_ssize << PAGE_SHIFT; DUMP_WRITE(dump_start, dump_size); } - /* - * Finally dump the task struct. Not be used by gdb, but - * could be useful - */ - set_fs(KERNEL_DS); - DUMP_WRITE(current, sizeof(*current)); end_coredump: set_fs(fs); return has_dumped; diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index b86feab..518bb99 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -50,7 +50,12 @@ /* * Reload arg registers from stack in case ptrace changed them. * We don't reload %eax because syscall_trace_enter() returned - * the value it wants us to use in the table lookup. + * the %rax value we should see. Instead, we just truncate that + * value to 32 bits again as we did on entry from user mode. + * If it's a new value set by user_regset during entry tracing, + * this matches the normal truncation of the user-mode value. + * If it's -1 to make us punt the syscall, then (u32)-1 is still + * an appropriately invalid value. */ .macro LOAD_ARGS32 offset, _r9=0 .if \_r9 @@ -60,6 +65,7 @@ movl \offset+48(%rsp),%edx movl \offset+56(%rsp),%esi movl \offset+64(%rsp),%edi + movl %eax,%eax /* zero extension */ .endm .macro CFI_STARTPROC32 simple @@ -153,7 +159,7 @@ ENTRY(ia32_sysenter_target) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) CFI_REMEMBER_STATE jnz sysenter_tracesys - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys sysenter_do_call: IA32_ARG_FIXUP @@ -195,7 +201,7 @@ sysexit_from_sys_call: movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ call audit_syscall_entry movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys movl %ebx,%edi /* reload 1st syscall arg */ movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ @@ -248,7 +254,7 @@ sysenter_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ jmp sysenter_do_call CFI_ENDPROC @@ -314,7 +320,7 @@ ENTRY(ia32_cstar_target) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) CFI_REMEMBER_STATE jnz cstar_tracesys - cmpl $IA32_NR_syscalls-1,%eax + cmpq $IA32_NR_syscalls-1,%rax ja ia32_badsys cstar_do_call: IA32_ARG_FIXUP 1 @@ -367,7 +373,7 @@ cstar_tracesys: LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ RESTORE_REST xchgl %ebp,%r9d - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ jmp cstar_do_call END(ia32_cstar_target) @@ -425,7 +431,7 @@ ENTRY(ia32_syscall) orl $TS_COMPAT,TI_status(%r10) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) jnz ia32_tracesys - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys ia32_do_call: IA32_ARG_FIXUP @@ -444,7 +450,7 @@ ia32_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - cmpl $(IA32_NR_syscalls-1),%eax + cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ jmp ia32_do_call END(ia32_syscall) diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h index d2544f1..cb03037 100644 --- a/arch/x86/include/asm/amd_iommu_proto.h +++ b/arch/x86/include/asm/amd_iommu_proto.h @@ -38,4 +38,10 @@ static inline void amd_iommu_stats_init(void) { } #endif /* !CONFIG_AMD_IOMMU_STATS */ +static inline bool is_rd890_iommu(struct pci_dev *pdev) +{ + return (pdev->vendor == PCI_VENDOR_ID_ATI) && + (pdev->device == PCI_DEVICE_ID_RD890_IOMMU); +} + #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 7014e88..0861618 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -368,6 +368,9 @@ struct amd_iommu { /* capabilities of that IOMMU read from ACPI */ u32 cap; + /* flags read from acpi table */ + u8 acpi_flags; + /* * Capability pointer. There could be more than one IOMMU per PCI * device function if there are more than one AMD IOMMU capability @@ -411,6 +414,15 @@ struct amd_iommu { /* default dma_ops domain for that IOMMU */ struct dma_ops_domain *default_dom; + + /* + * This array is required to work around a potential BIOS bug. + * The BIOS may miss to restore parts of the PCI configuration + * space when the system resumes from S3. The result is that the + * IOMMU does not execute commands anymore which leads to system + * failure. + */ + u32 cache_cfg[4]; }; /* diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 545776e..bafd80d 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h @@ -309,7 +309,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr) static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr) { return ((1UL << (nr % BITS_PER_LONG)) & - (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; + (addr[nr / BITS_PER_LONG])) != 0; } static inline int variable_test_bit(int nr, volatile const unsigned long *addr) diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 306160e..1d9cd27 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) return (u32)(unsigned long)uptr; } -static inline void __user *compat_alloc_user_space(long len) +static inline void __user *arch_compat_alloc_user_space(long len) { struct pt_regs *regs = task_pt_regs(current); return (void __user *)regs->sp - len; diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 781a50b..3f76523 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -168,6 +168,7 @@ #define X86_FEATURE_XSAVEOPT (7*32+ 4) /* Optimized Xsave */ #define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ +#define X86_FEATURE_DTS (7*32+ 7) /* Digital Thermal Sensor */ /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ @@ -296,6 +297,7 @@ extern const char * const x86_power_flags[32]; #endif /* CONFIG_X86_64 */ +#if __GNUC__ >= 4 /* * Static testing of CPU features. Used the same as boot_cpu_has(). * These are only valid after alternatives have run, but will statically @@ -304,7 +306,7 @@ extern const char * const x86_power_flags[32]; */ static __always_inline __pure bool __static_cpu_has(u16 bit) { -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#if __GNUC__ > 4 || __GNUC_MINOR__ >= 5 asm goto("1: jmp %l[t_no]\n" "2:\n" ".section .altinstructions,\"a\"\n" @@ -345,7 +347,6 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) #endif } -#if __GNUC__ >= 4 #define static_cpu_has(bit) \ ( \ __builtin_constant_p(boot_cpu_has(bit)) ? \ diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index 004e6e2..1d5c08a 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -68,7 +68,6 @@ extern unsigned long force_hpet_address; extern u8 hpet_blockid; extern int hpet_force_user; extern u8 hpet_msi_disable; -extern u8 hpet_readback_cmp; extern int is_hpet_enabled(void); extern int hpet_enable(void); extern void hpet_disable(void); diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h index 528a11e..824ca07 100644 --- a/arch/x86/include/asm/hw_breakpoint.h +++ b/arch/x86/include/asm/hw_breakpoint.h @@ -20,7 +20,7 @@ struct arch_hw_breakpoint { #include <linux/list.h> /* Available HW breakpoint length encodings */ -#define X86_BREAKPOINT_LEN_X 0x00 +#define X86_BREAKPOINT_LEN_X 0x40 #define X86_BREAKPOINT_LEN_1 0x40 #define X86_BREAKPOINT_LEN_2 0x44 #define X86_BREAKPOINT_LEN_4 0x4c diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 0925676..fedf32a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -11,6 +11,8 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_tsc.o = -pg CFLAGS_REMOVE_rtc.o = -pg CFLAGS_REMOVE_paravirt-spinlocks.o = -pg +CFLAGS_REMOVE_pvclock.o = -pg +CFLAGS_REMOVE_kvmclock.o = -pg CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_early_printk.o = -pg endif diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index fb7a5f0..fb16f17 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c @@ -61,7 +61,7 @@ struct cstate_entry { unsigned int ecx; } states[ACPI_PROCESSOR_MAX_POWER]; }; -static struct cstate_entry *cpu_cstate_entry; /* per CPU ptr */ +static struct cstate_entry __percpu *cpu_cstate_entry; /* per CPU ptr */ static short mwait_supported[ACPI_PROCESSOR_MAX_POWER]; diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index fa044e1..679b645 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1953,6 +1953,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, size_t size, int dir) { + dma_addr_t flush_addr; dma_addr_t i, start; unsigned int pages; @@ -1960,6 +1961,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, (dma_addr + size > dma_dom->aperture_size)) return; + flush_addr = dma_addr; pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); dma_addr &= PAGE_MASK; start = dma_addr; @@ -1974,7 +1976,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, dma_ops_free_addresses(dma_dom, dma_addr, pages); if (amd_iommu_unmap_flush || dma_dom->need_flush) { - iommu_flush_pages(&dma_dom->domain, dma_addr, size); + iommu_flush_pages(&dma_dom->domain, flush_addr, size); dma_dom->need_flush = false; } } diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 3cc63e2..5a170cb 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -632,6 +632,13 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu) iommu->last_device = calc_devid(MMIO_GET_BUS(range), MMIO_GET_LD(range)); iommu->evt_msi_num = MMIO_MSI_NUM(misc); + + if (is_rd890_iommu(iommu->dev)) { + pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]); + pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]); + pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]); + pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]); + } } /* @@ -649,29 +656,9 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, struct ivhd_entry *e; /* - * First set the recommended feature enable bits from ACPI - * into the IOMMU control registers + * First save the recommended feature enable bits from ACPI */ - h->flags & IVHD_FLAG_HT_TUN_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : - iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); - - h->flags & IVHD_FLAG_PASSPW_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : - iommu_feature_disable(iommu, CONTROL_PASSPW_EN); - - h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : - iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); - - h->flags & IVHD_FLAG_ISOC_EN_MASK ? - iommu_feature_enable(iommu, CONTROL_ISOC_EN) : - iommu_feature_disable(iommu, CONTROL_ISOC_EN); - - /* - * make IOMMU memory accesses cache coherent - */ - iommu_feature_enable(iommu, CONTROL_COHERENT_EN); + iommu->acpi_flags = h->flags; /* * Done. Now parse the device entries @@ -1116,6 +1103,40 @@ static void init_device_table(void) } } +static void iommu_init_flags(struct amd_iommu *iommu) +{ + iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : + iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); + + iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : + iommu_feature_disable(iommu, CONTROL_PASSPW_EN); + + iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : + iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); + + iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ? + iommu_feature_enable(iommu, CONTROL_ISOC_EN) : + iommu_feature_disable(iommu, CONTROL_ISOC_EN); + + /* + * make IOMMU memory accesses cache coherent + */ + iommu_feature_enable(iommu, CONTROL_COHERENT_EN); +} + +static void iommu_apply_quirks(struct amd_iommu *iommu) +{ + if (is_rd890_iommu(iommu->dev)) { + pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]); + pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]); + pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]); + pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]); + } +} + /* * This function finally enables all IOMMUs found in the system after * they have been initialized @@ -1126,6 +1147,8 @@ static void enable_iommus(void) for_each_iommu(iommu) { iommu_disable(iommu); + iommu_apply_quirks(iommu); + iommu_init_flags(iommu); iommu_set_device_table(iommu); iommu_enable_command_buffer(iommu); iommu_enable_event_buffer(iommu); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index f1efeba..5c5b8f3 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -306,14 +306,19 @@ void arch_init_copy_chip_data(struct irq_desc *old_desc, old_cfg = old_desc->chip_data; - memcpy(cfg, old_cfg, sizeof(struct irq_cfg)); + cfg->vector = old_cfg->vector; + cfg->move_in_progress = old_cfg->move_in_progress; + cpumask_copy(cfg->domain, old_cfg->domain); + cpumask_copy(cfg->old_domain, old_cfg->old_domain); init_copy_irq_2_pin(old_cfg, cfg, node); } -static void free_irq_cfg(struct irq_cfg *old_cfg) +static void free_irq_cfg(struct irq_cfg *cfg) { - kfree(old_cfg); + free_cpumask_var(cfg->domain); + free_cpumask_var(cfg->old_domain); + kfree(cfg); } void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 7b598b8..f744f54 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -698,9 +698,11 @@ void __init uv_system_init(void) for (j = 0; j < 64; j++) { if (!test_bit(j, &present)) continue; - uv_blade_info[blade].pnode = (i * 64 + j); + pnode = (i * 64 + j); + uv_blade_info[blade].pnode = pnode; uv_blade_info[blade].nr_possible_cpus = 0; uv_blade_info[blade].nr_online_cpus = 0; + max_pnode = max(pnode, max_pnode); blade++; } } @@ -738,7 +740,6 @@ void __init uv_system_init(void) uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid); uv_node_to_blade[nid] = blade; uv_cpu_to_blade[cpu] = blade; - max_pnode = max(pnode, max_pnode); } /* Add blade/pnode info for nodes without cpus */ @@ -750,7 +751,6 @@ void __init uv_system_init(void) pnode = (paddr >> m_val) & pnode_mask; blade = boot_pnode_to_blade(pnode); uv_node_to_blade[nid] = blade; - max_pnode = max(pnode, max_pnode); } map_gru_high(max_pnode); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 490dac6..f2f9ac7 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -545,7 +545,7 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c) } } -static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) +void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) { u32 tfms, xlvl; u32 ebx; diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index 3624e8a..f668bb1 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h @@ -33,5 +33,6 @@ extern const struct cpu_dev *const __x86_cpu_dev_start[], *const __x86_cpu_dev_end[]; extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c); +extern void get_cpu_cap(struct cpuinfo_x86 *c); #endif diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c index 994230d..4f6f679 100644 --- a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c @@ -368,16 +368,22 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle) return -ENODEV; out_obj = output.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) - return -ENODEV; + if (out_obj->type != ACPI_TYPE_BUFFER) { + ret = -ENODEV; + goto out_free; + } errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); - if (errors) - return -ENODEV; + if (errors) { + ret = -ENODEV; + goto out_free; + } supported = *((u32 *)(out_obj->buffer.pointer + 4)); - if (!(supported & 0x1)) - return -ENODEV; + if (!(supported & 0x1)) { + ret = -ENODEV; + goto out_free; + } out_free: kfree(output.pointer); diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 85f69cd..b438944 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -39,6 +39,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID; wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable); c->cpuid_level = cpuid_eax(0); + get_cpu_cap(c); } } diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 5e97529..39aaee5 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -141,6 +141,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) address = (low & MASK_BLKPTR_LO) >> 21; if (!address) break; + address += MCG_XBLK_ADDR; } else ++address; @@ -148,12 +149,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) if (rdmsr_safe(address, &low, &high)) break; - if (!(high & MASK_VALID_HI)) { - if (block) - continue; - else - break; - } + if (!(high & MASK_VALID_HI)) + continue; if (!(high & MASK_CNTP_HI) || (high & MASK_LOCKED_HI)) diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index d9368ee..169d880 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -216,7 +216,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev, err = sysfs_add_file_to_group(&sys_dev->kobj, &attr_core_power_limit_count.attr, thermal_attr_group.name); - if (cpu_has(c, X86_FEATURE_PTS)) + if (cpu_has(c, X86_FEATURE_PTS)) { err = sysfs_add_file_to_group(&sys_dev->kobj, &attr_package_throttle_count.attr, thermal_attr_group.name); @@ -224,6 +224,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev, err = sysfs_add_file_to_group(&sys_dev->kobj, &attr_package_power_limit_count.attr, thermal_attr_group.name); + } return err; } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 3efdf28..03a5b03 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -102,6 +102,7 @@ struct cpu_hw_events { */ struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; + unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; int enabled; int n_events; @@ -1010,6 +1011,7 @@ static int x86_pmu_start(struct perf_event *event) x86_perf_event_set_period(event); cpuc->events[idx] = event; __set_bit(idx, cpuc->active_mask); + __set_bit(idx, cpuc->running); x86_pmu.enable(event); perf_event_update_userpage(event); @@ -1141,8 +1143,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_events); for (idx = 0; idx < x86_pmu.num_counters; idx++) { - if (!test_bit(idx, cpuc->active_mask)) + if (!test_bit(idx, cpuc->active_mask)) { + /* + * Though we deactivated the counter some cpus + * might still deliver spurious interrupts still + * in flight. Catch them: + */ + if (__test_and_clear_bit(idx, cpuc->running)) + handled++; continue; + } event = cpuc->events[idx]; hwc = &event->hw; diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index b560db3..2490151 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -660,8 +660,12 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) for (idx = 0; idx < x86_pmu.num_counters; idx++) { int overflow; - if (!test_bit(idx, cpuc->active_mask)) + if (!test_bit(idx, cpuc->active_mask)) { + /* catch in-flight IRQs */ + if (__test_and_clear_bit(idx, cpuc->running)) + handled++; continue; + } event = cpuc->events[idx]; hwc = &event->hw; diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index 34b4dad..d490795 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -31,6 +31,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) const struct cpuid_bit *cb; static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { + { X86_FEATURE_DTS, CR_EAX, 0, 0x00000006, 0 }, { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index e5cc7e8..ebdb85c 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -18,7 +18,6 @@ #include <asm/apic.h> #include <asm/iommu.h> #include <asm/gart.h> -#include <asm/hpet.h> static void __init fix_hypertransport_config(int num, int slot, int func) { @@ -192,21 +191,6 @@ static void __init ati_bugs_contd(int num, int slot, int func) } #endif -/* - * Force the read back of the CMP register in hpet_next_event() - * to work around the problem that the CMP register write seems to be - * delayed. See hpet_next_event() for details. - * - * We do this on all SMBUS incarnations for now until we have more - * information about the affected chipsets. - */ -static void __init ati_hpet_bugs(int num, int slot, int func) -{ -#ifdef CONFIG_HPET_TIMER - hpet_readback_cmp = 1; -#endif -} - #define QFLAG_APPLY_ONCE 0x1 #define QFLAG_APPLIED 0x2 #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) @@ -236,8 +220,6 @@ static struct chipset early_qrk[] __initdata = { PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, - { PCI_VENDOR_ID_ATI, PCI_ANY_ID, - PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_hpet_bugs }, {} }; diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 351f9c0..7494999 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -35,7 +35,6 @@ unsigned long hpet_address; u8 hpet_blockid; /* OS timer block num */ u8 hpet_msi_disable; -u8 hpet_readback_cmp; #ifdef CONFIG_PCI_MSI static unsigned long hpet_num_timers; @@ -395,23 +394,27 @@ static int hpet_next_event(unsigned long delta, * at that point and we would wait for the next hpet interrupt * forever. We found out that reading the CMP register back * forces the transfer so we can rely on the comparison with - * the counter register below. + * the counter register below. If the read back from the + * compare register does not match the value we programmed + * then we might have a real hardware problem. We can not do + * much about it here, but at least alert the user/admin with + * a prominent warning. * - * That works fine on those ATI chipsets, but on newer Intel - * chipsets (ICH9...) this triggers due to an erratum: Reading - * the comparator immediately following a write is returning - * the old value. + * An erratum on some chipsets (ICH9,..), results in + * comparator read immediately following a write returning old + * value. Workaround for this is to read this value second + * time, when first read returns old value. * - * We restrict the read back to the affected ATI chipsets (set - * by quirks) and also run it with hpet=verbose for debugging - * purposes. + * In fact the write to the comparator register is delayed up + * to two HPET cycles so the workaround we tried to restrict + * the readback to those known to be borked ATI chipsets + * failed miserably. So we give up on optimizations forever + * and penalize all HPET incarnations unconditionally. */ - if (hpet_readback_cmp || hpet_verbose) { - u32 cmp = hpet_readl(HPET_Tn_CMP(timer)); - - if (cmp != cnt) + if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) { + if (hpet_readl(HPET_Tn_CMP(timer)) != cnt) printk_once(KERN_WARNING - "hpet: compare register read back failed.\n"); + "hpet: compare register read back failed.\n"); } return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; @@ -503,7 +506,7 @@ static int hpet_assign_irq(struct hpet_dev *dev) { unsigned int irq; - irq = create_irq(); + irq = create_irq_nr(0, -1); if (!irq) return -EINVAL; diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index a474ec3..ff15c9d 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -206,11 +206,27 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp) int arch_bp_generic_fields(int x86_len, int x86_type, int *gen_len, int *gen_type) { - /* Len */ - switch (x86_len) { - case X86_BREAKPOINT_LEN_X: + /* Type */ + switch (x86_type) { + case X86_BREAKPOINT_EXECUTE: + if (x86_len != X86_BREAKPOINT_LEN_X) + return -EINVAL; + + *gen_type = HW_BREAKPOINT_X; *gen_len = sizeof(long); + return 0; + case X86_BREAKPOINT_WRITE: + *gen_type = HW_BREAKPOINT_W; break; + case X86_BREAKPOINT_RW: + *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; + break; + default: + return -EINVAL; + } + + /* Len */ + switch (x86_len) { case X86_BREAKPOINT_LEN_1: *gen_len = HW_BREAKPOINT_LEN_1; break; @@ -229,21 +245,6 @@ int arch_bp_generic_fields(int x86_len, int x86_type, return -EINVAL; } - /* Type */ - switch (x86_type) { - case X86_BREAKPOINT_EXECUTE: - *gen_type = HW_BREAKPOINT_X; - break; - case X86_BREAKPOINT_WRITE: - *gen_type = HW_BREAKPOINT_W; - break; - case X86_BREAKPOINT_RW: - *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; - break; - default: - return -EINVAL; - } - return 0; } @@ -316,9 +317,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) ret = -EINVAL; switch (info->len) { - case X86_BREAKPOINT_LEN_X: - align = sizeof(long) -1; - break; case X86_BREAKPOINT_LEN_1: align = 0; break; diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index e0bc186..1c355c5 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -239,11 +239,10 @@ int module_finalize(const Elf_Ehdr *hdr, apply_paravirt(pseg, pseg + para->sh_size); } - return module_bug_finalize(hdr, sechdrs, me); + return 0; } void module_arch_cleanup(struct module *mod) { alternatives_smp_module_del(mod); - module_bug_cleanup(mod); } diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index bc5b9b8..81ed28c 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -766,7 +766,6 @@ static void init_vmcb(struct vcpu_svm *svm) control->iopm_base_pa = iopm_base; control->msrpm_base_pa = __pa(svm->msrpm); - control->tsc_offset = 0; control->int_ctl = V_INTR_MASKING_MASK; init_seg(&save->es); @@ -902,6 +901,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; svm->asid_generation = 0; init_vmcb(svm); + svm->vmcb->control.tsc_offset = 0-native_read_tsc(); err = fx_init(&svm->vcpu); if (err) diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 9257510..9d5f558 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -324,9 +324,8 @@ static void lguest_load_gdt(const struct desc_ptr *desc) } /* - * For a single GDT entry which changes, we do the lazy thing: alter our GDT, - * then tell the Host to reload the entire thing. This operation is so rare - * that this naive implementation is reasonable. + * For a single GDT entry which changes, we simply change our copy and + * then tell the host about it. */ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum, const void *desc, int type) @@ -338,9 +337,13 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum, } /* - * OK, I lied. There are three "thread local storage" GDT entries which change + * There are three "thread local storage" GDT entries which change * on every context switch (these three entries are how glibc implements - * __thread variables). So we have a hypercall specifically for this case. + * __thread variables). As an optimization, we have a hypercall + * specifically for this case. + * + * Wouldn't it be nicer to have a general LOAD_GDT_ENTRIES hypercall + * which took a range of entries? */ static void lguest_load_tls(struct thread_struct *t, unsigned int cpu) { diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index f9897f7..9c0d0d3 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -420,9 +420,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) return -1; } - for_each_node_mask(i, nodes_parsed) - e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT, - nodes[i].end >> PAGE_SHIFT); + for (i = 0; i < num_node_memblks; i++) + e820_register_active_regions(memblk_nodeid[i], + node_memblk_range[i].start >> PAGE_SHIFT, + node_memblk_range[i].end >> PAGE_SHIFT); + /* for out of order entries in SRAT */ sort_node_map(); if (!nodes_cover_memory(nodes)) { diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index cfe4faa..f1575c9 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -671,7 +671,10 @@ static int __init ppro_init(char **cpu_type) case 14: *cpu_type = "i386/core"; break; - case 15: case 23: + case 0x0f: + case 0x16: + case 0x17: + case 0x1d: *cpu_type = "i386/core_2"; break; case 0x1a: diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 1a5353a..b2bb5aa 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -489,8 +489,9 @@ static void xen_hvm_setup_cpu_clockevents(void) __init void xen_hvm_init_time_ops(void) { /* vector callback is needed otherwise we cannot receive interrupts - * on cpu > 0 */ - if (!xen_have_vector_callback && num_present_cpus() > 1) + * on cpu > 0 and at this point we don't know how many cpus are + * available */ + if (!xen_have_vector_callback) return; if (!xen_feature(XENFEAT_hvm_safe_pvclock)) { printk(KERN_INFO "Xen doesn't support pvclock on HVM," diff --git a/block/blk-map.c b/block/blk-map.c index c65d759..ade0a08 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -307,7 +307,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, return PTR_ERR(bio); if (rq_data_dir(rq) == WRITE) - bio->bi_rw |= (1 << REQ_WRITE); + bio->bi_rw |= REQ_WRITE; if (do_copy) rq->cmd_flags |= REQ_COPY_USER; diff --git a/block/blk-merge.c b/block/blk-merge.c index 3b0cd42..eafc94f 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -362,6 +362,18 @@ static int attempt_merge(struct request_queue *q, struct request *req, return 0; /* + * Don't merge file system requests and discard requests + */ + if ((req->cmd_flags & REQ_DISCARD) != (next->cmd_flags & REQ_DISCARD)) + return 0; + + /* + * Don't merge discard requests and secure discard requests + */ + if ((req->cmd_flags & REQ_SECURE) != (next->cmd_flags & REQ_SECURE)) + return 0; + + /* * not contiguous */ if (blk_rq_pos(req) + blk_rq_sectors(req) != blk_rq_pos(next)) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index f65c6f0..9eba291 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1019,10 +1019,20 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create) */ atomic_set(&cfqg->ref, 1); - /* Add group onto cgroup list */ - sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); - cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, + /* + * Add group onto cgroup list. It might happen that bdi->dev is + * not initiliazed yet. Initialize this new group without major + * and minor info and this info will be filled in once a new thread + * comes for IO. See code above. + */ + if (bdi->dev) { + sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); + cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, MKDEV(major, minor)); + } else + cfq_blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd, + 0); + cfqg->weight = blkcg_get_weight(blkcg, cfqg->blkg.dev); /* Add group on cfqd list */ diff --git a/block/elevator.c b/block/elevator.c index 205b09a..4e11559 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -938,6 +938,7 @@ int elv_register_queue(struct request_queue *q) } } kobject_uevent(&e->kobj, KOBJ_ADD); + e->registered = 1; } return error; } @@ -947,6 +948,7 @@ static void __elv_unregister_queue(struct elevator_queue *e) { kobject_uevent(&e->kobj, KOBJ_REMOVE); kobject_del(&e->kobj); + e->registered = 0; } void elv_unregister_queue(struct request_queue *q) @@ -1042,11 +1044,13 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) spin_unlock_irq(q->queue_lock); - __elv_unregister_queue(old_elevator); + if (old_elevator->registered) { + __elv_unregister_queue(old_elevator); - err = elv_register_queue(q); - if (err) - goto fail_register; + err = elv_register_queue(q); + if (err) + goto fail_register; + } /* * finally exit old elevator and turn off BYPASS. diff --git a/drivers/Makefile b/drivers/Makefile index ae47344..a2aea53 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -50,7 +50,7 @@ obj-$(CONFIG_SPI) += spi/ obj-y += net/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_FUSION) += message/ -obj-$(CONFIG_FIREWIRE) += firewire/ +obj-y += firewire/ obj-y += ieee1394/ obj-$(CONFIG_UIO) += uio/ obj-y += cdrom/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b811f21..88681ac 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -105,7 +105,7 @@ config ACPI_EC_DEBUGFS Be aware that using this interface can confuse your Embedded Controller in a way that a normal reboot is not enough. You then - have to power of your system, and remove the laptop battery for + have to power off your system, and remove the laptop battery for some seconds. An Embedded Controller typically is available on laptops and reads sensor values like battery state and temperature. diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index b76848c..6b115f6 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -382,31 +382,32 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) device_remove_file(&device->dev, &dev_attr_rrtime); } -/* Query firmware how many CPUs should be idle */ -static int acpi_pad_pur(acpi_handle handle, int *num_cpus) +/* + * Query firmware how many CPUs should be idle + * return -1 on failure + */ +static int acpi_pad_pur(acpi_handle handle) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *package; - int rev, num, ret = -EINVAL; + int num = -1; if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) - return -EINVAL; + return num; if (!buffer.length || !buffer.pointer) - return -EINVAL; + return num; package = buffer.pointer; - if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) - goto out; - rev = package->package.elements[0].integer.value; - num = package->package.elements[1].integer.value; - if (rev != 1 || num < 0) - goto out; - *num_cpus = num; - ret = 0; -out: + + if (package->type == ACPI_TYPE_PACKAGE && + package->package.count == 2 && + package->package.elements[0].integer.value == 1) /* rev 1 */ + + num = package->package.elements[1].integer.value; + kfree(buffer.pointer); - return ret; + return num; } /* Notify firmware how many CPUs are idle */ @@ -433,7 +434,8 @@ static void acpi_pad_handle_notify(acpi_handle handle) uint32_t idle_cpus; mutex_lock(&isolated_cpus_lock); - if (acpi_pad_pur(handle, &num_cpus)) { + num_cpus = acpi_pad_pur(handle); + if (num_cpus < 0) { mutex_unlock(&isolated_cpus_lock); return; } diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index df85b53..7dad916 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -854,6 +854,7 @@ struct acpi_bit_register_info { ACPI_BITMASK_POWER_BUTTON_STATUS | \ ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ ACPI_BITMASK_RT_CLOCK_STATUS | \ + ACPI_BITMASK_PCIEXP_WAKE_DISABLE | \ ACPI_BITMASK_WAKE_STATUS) #define ACPI_BITMASK_TIMER_ENABLE 0x0001 diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 74c24d5..4093522 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -109,7 +109,7 @@ void acpi_ex_enter_interpreter(void) * * DESCRIPTION: Reacquire the interpreter execution region from within the * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with + * fatal system error. Used in conjunction with * relinquish_interpreter * ******************************************************************************/ diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 22cfcfb..491191e 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -149,7 +149,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) /* * 16-, 32-, and 64-bit cases must use the move macros that perform - * endian conversion and/or accomodate hardware that cannot perform + * endian conversion and/or accommodate hardware that cannot perform * misaligned memory transfers */ case ACPI_RSC_MOVE16: diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 907e350..fca34cc 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -34,6 +34,6 @@ config ACPI_APEI_ERST_DEBUG depends on ACPI_APEI help ERST is a way provided by APEI to save and retrieve hardware - error infomation to and from a persistent store. Enable this + error information to and from a persistent store. Enable this if you want to debugging and testing the ERST kernel support and firmware implementation. diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 73fd0c7..4a904a4 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -445,11 +445,15 @@ EXPORT_SYMBOL_GPL(apei_resources_sub); int apei_resources_request(struct apei_resources *resources, const char *desc) { - struct apei_res *res, *res_bak; + struct apei_res *res, *res_bak = NULL; struct resource *r; + int rc; - apei_resources_sub(resources, &apei_resources_all); + rc = apei_resources_sub(resources, &apei_resources_all); + if (rc) + return rc; + rc = -EINVAL; list_for_each_entry(res, &resources->iomem, list) { r = request_mem_region(res->start, res->end - res->start, desc); @@ -475,7 +479,11 @@ int apei_resources_request(struct apei_resources *resources, } } - apei_resources_merge(&apei_resources_all, resources); + rc = apei_resources_merge(&apei_resources_all, resources); + if (rc) { + pr_err(APEI_PFX "Fail to merge resources!\n"); + goto err_unmap_ioport; + } return 0; err_unmap_ioport: @@ -491,12 +499,13 @@ err_unmap_iomem: break; release_mem_region(res->start, res->end - res->start); } - return -EINVAL; + return rc; } EXPORT_SYMBOL_GPL(apei_resources_request); void apei_resources_release(struct apei_resources *resources) { + int rc; struct apei_res *res; list_for_each_entry(res, &resources->iomem, list) @@ -504,7 +513,9 @@ void apei_resources_release(struct apei_resources *resources) list_for_each_entry(res, &resources->ioport, list) release_region(res->start, res->end - res->start); - apei_resources_sub(&apei_resources_all, resources); + rc = apei_resources_sub(&apei_resources_all, resources); + if (rc) + pr_err(APEI_PFX "Fail to sub resources!\n"); } EXPORT_SYMBOL_GPL(apei_resources_release); diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 465c885..cf29df6 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -426,7 +426,9 @@ DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, static int einj_check_table(struct acpi_table_einj *einj_tab) { - if (einj_tab->header_length != sizeof(struct acpi_table_einj)) + if ((einj_tab->header_length != + (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header))) + && (einj_tab->header_length != sizeof(struct acpi_table_einj))) return -EINVAL; if (einj_tab->header.length < sizeof(struct acpi_table_einj)) return -EINVAL; diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c index 5281ddd..da1228a 100644 --- a/drivers/acpi/apei/erst-dbg.c +++ b/drivers/acpi/apei/erst-dbg.c @@ -2,7 +2,7 @@ * APEI Error Record Serialization Table debug support * * ERST is a way provided by APEI to save and retrieve hardware error - * infomation to and from a persistent store. This file provide the + * information to and from a persistent store. This file provide the * debugging/testing support for ERST kernel support and firmware * implementation. * @@ -111,11 +111,13 @@ retry: goto out; } if (len > erst_dbg_buf_len) { - kfree(erst_dbg_buf); + void *p; rc = -ENOMEM; - erst_dbg_buf = kmalloc(len, GFP_KERNEL); - if (!erst_dbg_buf) + p = kmalloc(len, GFP_KERNEL); + if (!p) goto out; + kfree(erst_dbg_buf); + erst_dbg_buf = p; erst_dbg_buf_len = len; goto retry; } @@ -150,11 +152,13 @@ static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf, if (mutex_lock_interruptible(&erst_dbg_mutex)) return -EINTR; if (usize > erst_dbg_buf_len) { - kfree(erst_dbg_buf); + void *p; rc = -ENOMEM; - erst_dbg_buf = kmalloc(usize, GFP_KERNEL); - if (!erst_dbg_buf) + p = kmalloc(usize, GFP_KERNEL); + if (!p) goto out; + kfree(erst_dbg_buf); + erst_dbg_buf = p; erst_dbg_buf_len = usize; } rc = copy_from_user(erst_dbg_buf, ubuf, usize); diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 18645f4..1211c03 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -2,7 +2,7 @@ * APEI Error Record Serialization Table support * * ERST is a way provided by APEI to save and retrieve hardware error - * infomation to and from a persistent store. + * information to and from a persistent store. * * For more information about ERST, please refer to ACPI Specification * version 4.0, section 17.4. @@ -266,13 +266,30 @@ static int erst_exec_move_data(struct apei_exec_context *ctx, { int rc; u64 offset; + void *src, *dst; + + /* ioremap does not work in interrupt context */ + if (in_interrupt()) { + pr_warning(ERST_PFX + "MOVE_DATA can not be used in interrupt context"); + return -EBUSY; + } rc = __apei_exec_read_register(entry, &offset); if (rc) return rc; - memmove((void *)ctx->dst_base + offset, - (void *)ctx->src_base + offset, - ctx->var2); + + src = ioremap(ctx->src_base + offset, ctx->var2); + if (!src) + return -ENOMEM; + dst = ioremap(ctx->dst_base + offset, ctx->var2); + if (!dst) + return -ENOMEM; + + memmove(dst, src, ctx->var2); + + iounmap(src); + iounmap(dst); return 0; } @@ -750,7 +767,9 @@ __setup("erst_disable", setup_erst_disable); static int erst_check_table(struct acpi_table_erst *erst_tab) { - if (erst_tab->header_length != sizeof(struct acpi_table_erst)) + if ((erst_tab->header_length != + (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header))) + && (erst_tab->header_length != sizeof(struct acpi_table_einj))) return -EINVAL; if (erst_tab->header.length < sizeof(struct acpi_table_erst)) return -EINVAL; diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 385a605..0d505e5 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -302,7 +302,7 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) struct ghes *ghes = NULL; int rc = -EINVAL; - generic = ghes_dev->dev.platform_data; + generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data; if (!generic->enabled) return -ENODEV; diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 343168d..1a3508a 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -137,20 +137,23 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data) static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data) { - struct acpi_hest_generic *generic; struct platform_device *ghes_dev; struct ghes_arr *ghes_arr = data; int rc; if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) return 0; - generic = (struct acpi_hest_generic *)hest_hdr; - if (!generic->enabled) + + if (!((struct acpi_hest_generic *)hest_hdr)->enabled) return 0; ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id); if (!ghes_dev) return -ENOMEM; - ghes_dev->dev.platform_data = generic; + + rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *)); + if (rc) + goto err; + rc = platform_device_add(ghes_dev); if (rc) goto err; diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c index 8f8bd73..542e539 100644 --- a/drivers/acpi/atomicio.c +++ b/drivers/acpi/atomicio.c @@ -142,7 +142,7 @@ static void __iomem *acpi_pre_map(phys_addr_t paddr, list_add_tail_rcu(&map->list, &acpi_iomaps); spin_unlock_irqrestore(&acpi_iomaps_lock, flags); - return vaddr + (paddr - pg_off); + return map->vaddr + (paddr - map->paddr); err_unmap: iounmap(vaddr); return NULL; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index dc58402..9841720 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -273,7 +273,6 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_POWER_NOW, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 2bb28b9..af308d0 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -183,6 +183,8 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) { printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2006"); + acpi_osi_setup("!Windows 2006 SP1"); + acpi_osi_setup("!Windows 2006 SP2"); return 0; } static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) @@ -202,6 +204,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { + /* + * There have a NVIF method in MSI GX723 DSDT need call by Nvidia + * driver (e.g. nouveau) when user press brightness hotkey. + * Currently, nouveau driver didn't do the job and it causes there + * have a infinite while loop in DSDT when user press hotkey. + * We add MSI GX723's dmi information to this table for workaround + * this issue. + * Will remove MSI GX723 from the table after nouveau grows support. + */ + .callback = dmi_disable_osi_vista, + .ident = "MSI GX723", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "GX723"), + }, + }, + { .callback = dmi_disable_osi_vista, .ident = "Sony VGN-NS10J_S", .matches = { @@ -226,6 +245,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba Satellite L355", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"), + }, + }, + { .callback = dmi_disable_osi_win7, .ident = "ASUS K50IJ", .matches = { @@ -233,6 +260,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba P305D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 5c221ab..310e3b9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -55,7 +55,7 @@ EXPORT_SYMBOL(acpi_root_dir); static int set_power_nocheck(const struct dmi_system_id *id) { printk(KERN_NOTICE PREFIX "%s detected - " - "disable power check in power transistion\n", id->ident); + "disable power check in power transition\n", id->ident); acpi_power_nocheck = 1; return 0; } @@ -80,23 +80,15 @@ static int set_copy_dsdt(const struct dmi_system_id *id) static struct dmi_system_id dsdt_dmi_table[] __initdata = { /* - * Insyde BIOS on some TOSHIBA machines corrupt the DSDT. + * Invoke DSDT corruption work-around on all Toshiba Satellite. * https://bugzilla.kernel.org/show_bug.cgi?id=14679 */ { .callback = set_copy_dsdt, - .ident = "TOSHIBA Satellite A505", + .ident = "TOSHIBA Satellite", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"), - }, - }, - { - .callback = set_copy_dsdt, - .ident = "TOSHIBA Satellite L505D", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), }, }, {} @@ -1027,7 +1019,7 @@ static int __init acpi_init(void) /* * If the laptop falls into the DMI check table, the power state check - * will be disabled in the course of device power transistion. + * will be disabled in the course of device power transition. */ dmi_check_system(power_nocheck_dmi_table); diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 8a3b840..d94d295 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -369,7 +369,9 @@ static void __exit acpi_fan_exit(void) acpi_bus_unregister_driver(&acpi_fan_driver); +#ifdef CONFIG_ACPI_PROCFS remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); +#endif return; } diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e9699aa..bec561c 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -29,12 +29,6 @@ static int set_no_mwait(const struct dmi_system_id *id) static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { { - set_no_mwait, "IFL91 board", { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), - DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, - { set_no_mwait, "Extensa 5220", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -352,4 +346,5 @@ void __init acpi_early_processor_set_pdc(void) acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); + acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL); } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 1560218..347eb21 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -850,7 +850,7 @@ static int __init acpi_processor_init(void) printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", acpi_idle_driver.name); } else { - printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s", + printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n", cpuidle_get_driver()->name); } diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index ba1bd26..3a73a93 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -447,8 +447,8 @@ int acpi_processor_notify_smm(struct module *calling_module) if (!try_module_get(calling_module)) return -EINVAL; - /* is_done is set to negative if an error occured, - * and to postitive if _no_ error occured, but SMM + /* is_done is set to negative if an error occurred, + * and to postitive if _no_ error occurred, but SMM * was already notified. This avoids double notification * which might lead to unexpected results... */ diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index cf82989..4754ff6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -363,6 +363,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) return 0; } +static int __init init_nvs_nosave(const struct dmi_system_id *d) +{ + acpi_nvs_nosave(); + return 0; +} + static struct dmi_system_id __initdata acpisleep_dmi_table[] = { { .callback = init_old_suspend_ordering, @@ -397,6 +403,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), }, }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Everex StepNote Series", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 68e2e45..f8588f8 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -100,7 +100,7 @@ static const struct acpi_dlevel acpi_debug_levels[] = { ACPI_DEBUG_INIT(ACPI_LV_EVENTS), }; -static int param_get_debug_layer(char *buffer, struct kernel_param *kp) +static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) { int result = 0; int i; @@ -128,7 +128,7 @@ static int param_get_debug_layer(char *buffer, struct kernel_param *kp) return result; } -static int param_get_debug_level(char *buffer, struct kernel_param *kp) +static int param_get_debug_level(char *buffer, const struct kernel_param *kp) { int result = 0; int i; @@ -149,10 +149,18 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) return result; } -module_param_call(debug_layer, param_set_uint, param_get_debug_layer, - &acpi_dbg_layer, 0644); -module_param_call(debug_level, param_set_uint, param_get_debug_level, - &acpi_dbg_level, 0644); +static struct kernel_param_ops param_ops_debug_layer = { + .set = param_set_uint, + .get = param_get_debug_layer, +}; + +static struct kernel_param_ops param_ops_debug_level = { + .set = param_set_uint, + .get = param_get_debug_level, +}; + +module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644); +module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644); static char trace_method_name[6]; module_param_string(trace_method_name, trace_method_name, 6, 0644); diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index c5fef01..b836761 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -59,8 +59,8 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, "support\n")); *cap |= ACPI_VIDEO_BACKLIGHT; if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy))) - printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness " - "control misses _BQC function\n"); + printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, " + "cannot determine initial brightness\n"); /* We have backlight support, no need to scan further */ return AE_CTRL_TERMINATE; } diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ff1c945..99d0e5a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -90,6 +90,10 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); #endif +static struct scsi_host_template ahci_sht = { + AHCI_SHT("ahci"), +}; + static struct ata_port_operations ahci_vt8251_ops = { .inherits = &ahci_ops, .hardreset = ahci_vt8251_hardreset, diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 474427b..e5fdeeb 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -298,7 +298,17 @@ struct ahci_host_priv { extern int ahci_ignore_sss; -extern struct scsi_host_template ahci_sht; +extern struct device_attribute *ahci_shost_attrs[]; +extern struct device_attribute *ahci_sdev_attrs[]; + +#define AHCI_SHT(drv_name) \ + ATA_NCQ_SHT(drv_name), \ + .can_queue = AHCI_MAX_CMDS - 1, \ + .sg_tablesize = AHCI_MAX_SG, \ + .dma_boundary = AHCI_DMA_BOUNDARY, \ + .shost_attrs = ahci_shost_attrs, \ + .sdev_attrs = ahci_sdev_attrs + extern struct ata_port_operations ahci_ops; void ahci_save_initial_config(struct device *dev, diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 4e97f33..84b6432 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -23,6 +23,10 @@ #include <linux/ahci_platform.h> #include "ahci.h" +static struct scsi_host_template ahci_platform_sht = { + AHCI_SHT("ahci_platform"), +}; + static int __init ahci_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -145,7 +149,7 @@ static int __init ahci_probe(struct platform_device *pdev) ahci_print_info(host, "platform"); rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, - &ahci_sht); + &ahci_platform_sht); if (rc) goto err0; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 68dc678..8eea309 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -121,7 +121,7 @@ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO, ahci_read_em_buffer, ahci_store_em_buffer); -static struct device_attribute *ahci_shost_attrs[] = { +struct device_attribute *ahci_shost_attrs[] = { &dev_attr_link_power_management_policy, &dev_attr_em_message_type, &dev_attr_em_message, @@ -132,22 +132,14 @@ static struct device_attribute *ahci_shost_attrs[] = { &dev_attr_em_buffer, NULL }; +EXPORT_SYMBOL_GPL(ahci_shost_attrs); -static struct device_attribute *ahci_sdev_attrs[] = { +struct device_attribute *ahci_sdev_attrs[] = { &dev_attr_sw_activity, &dev_attr_unload_heads, NULL }; - -struct scsi_host_template ahci_sht = { - ATA_NCQ_SHT("ahci"), - .can_queue = AHCI_MAX_CMDS - 1, - .sg_tablesize = AHCI_MAX_SG, - .dma_boundary = AHCI_DMA_BOUNDARY, - .shost_attrs = ahci_shost_attrs, - .sdev_attrs = ahci_sdev_attrs, -}; -EXPORT_SYMBOL_GPL(ahci_sht); +EXPORT_SYMBOL_GPL(ahci_sdev_attrs); struct ata_port_operations ahci_ops = { .inherits = &sata_pmp_port_ops, diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index ee9ddeb..8cb0347 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -3156,7 +3156,6 @@ static int __devinit ia_init_one(struct pci_dev *pdev, { struct atm_dev *dev; IADEV *iadev; - unsigned long flags; int ret; iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); @@ -3188,19 +3187,14 @@ static int __devinit ia_init_one(struct pci_dev *pdev, ia_dev[iadev_count] = iadev; _ia_dev[iadev_count] = dev; iadev_count++; - spin_lock_init(&iadev->misc_lock); - /* First fixes first. I don't want to think about this now. */ - spin_lock_irqsave(&iadev->misc_lock, flags); if (ia_init(dev) || ia_start(dev)) { IF_INIT(printk("IA register failed!\n");) iadev_count--; ia_dev[iadev_count] = NULL; _ia_dev[iadev_count] = NULL; - spin_unlock_irqrestore(&iadev->misc_lock, flags); ret = -EINVAL; goto err_out_deregister_dev; } - spin_unlock_irqrestore(&iadev->misc_lock, flags); IF_EVENT(printk("iadev_count = %d\n", iadev_count);) iadev->next_board = ia_boards; diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index b2cd20f..077735e 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h @@ -1022,7 +1022,7 @@ typedef struct iadev_t { struct dle_q rx_dle_q; struct free_desc_q *rx_free_desc_qhead; struct sk_buff_head rx_dma_q; - spinlock_t rx_lock, misc_lock; + spinlock_t rx_lock; struct atm_vcc **rx_open; /* list of all open VCs */ u16 num_rx_desc, rx_buf_sz, rxing; u32 rx_pkt_ram, rx_tmp_cnt; diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index f916ddf..f46138a 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -444,6 +444,7 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev); struct solos_card *card = atmdev->dev_data; struct sk_buff *skb; + unsigned int len; spin_lock(&card->cli_queue_lock); skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]); @@ -451,11 +452,12 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, if(skb == NULL) return sprintf(buf, "No data.\n"); - memcpy(buf, skb->data, skb->len); - dev_dbg(&card->dev->dev, "len: %d\n", skb->len); + len = skb->len; + memcpy(buf, skb->data, len); + dev_dbg(&card->dev->dev, "len: %d\n", len); kfree_skb(skb); - return skb->len; + return len; } static int send_command(struct solos_card *card, int dev, const char *buf, size_t size) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 6124c2f..5e4fadc 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -4792,7 +4792,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, clean4: kfree(h->cmd_pool_bits); /* Free up sg elements */ - for (k = 0; k < h->nr_cmds; k++) + for (k-- ; k >= 0; k--) kfree(h->scatter_list[k]); kfree(h->scatter_list); cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index b1cbeb5..37a2bb5 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2369,7 +2369,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) pkt_shrink_pktlist(pd); } -static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) +static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor) { if (dev_minor >= MAX_WRITERS) return NULL; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 2aafafc..1101e25 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -202,6 +202,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) struct virtio_blk *vblk = disk->private_data; struct request *req; struct bio *bio; + int err; bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES, GFP_KERNEL); @@ -215,7 +216,10 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) } req->cmd_type = REQ_TYPE_SPECIAL; - return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); + err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); + blk_put_request(req); + + return err; } static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode, diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index eab58db..cd18493 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -806,6 +806,8 @@ static const struct intel_driver_description { "G45/G43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, "B43", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG, + "B43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, "G41", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index ee189c7..d09b1ab 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -186,6 +186,8 @@ #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 #define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40 #define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 +#define PCI_DEVICE_ID_INTEL_B43_1_HB 0x2E90 +#define PCI_DEVICE_ID_INTEL_B43_1_IG 0x2E92 #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 #define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00 diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 3822b4f..7bd7c45 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -305,6 +305,9 @@ static int num_force_kipmid; #ifdef CONFIG_PCI static int pci_registered; #endif +#ifdef CONFIG_ACPI +static int pnp_registered; +#endif #ifdef CONFIG_PPC_OF static int of_registered; #endif @@ -2126,7 +2129,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, { struct acpi_device *acpi_dev; struct smi_info *info; - struct resource *res; + struct resource *res, *res_second; acpi_handle handle; acpi_status status; unsigned long long tmp; @@ -2182,13 +2185,13 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, info->io.addr_data = res->start; info->io.regspacing = DEFAULT_REGSPACING; - res = pnp_get_resource(dev, + res_second = pnp_get_resource(dev, (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? IORESOURCE_IO : IORESOURCE_MEM, 1); - if (res) { - if (res->start > info->io.addr_data) - info->io.regspacing = res->start - info->io.addr_data; + if (res_second) { + if (res_second->start > info->io.addr_data) + info->io.regspacing = res_second->start - info->io.addr_data; } info->io.regsize = DEFAULT_REGSPACING; info->io.regshift = 0; @@ -3359,6 +3362,7 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_ACPI pnp_register_driver(&ipmi_pnp_driver); + pnp_registered = 1; #endif #ifdef CONFIG_DMI @@ -3526,7 +3530,8 @@ static __exit void cleanup_ipmi_si(void) pci_unregister_driver(&ipmi_pci_driver); #endif #ifdef CONFIG_ACPI - pnp_unregister_driver(&ipmi_pnp_driver); + if (pnp_registered) + pnp_unregister_driver(&ipmi_pnp_driver); #endif #ifdef CONFIG_PPC_OF diff --git a/drivers/char/mem.c b/drivers/char/mem.c index a398ecd..1f528fa 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -788,10 +788,11 @@ static const struct file_operations zero_fops = { /* * capabilities for /dev/zero * - permits private mappings, "copies" are taken of the source of zeros + * - no writeback happens */ static struct backing_dev_info zero_bdi = { .name = "char/mem", - .capabilities = BDI_CAP_MAP_COPY, + .capabilities = BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK, }; static const struct file_operations full_fops = { diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 942a982..c810481 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -596,6 +596,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, ssize_t ret; bool nonblock; + /* Userspace could be out to fool us */ + if (!count) + return 0; + port = filp->private_data; nonblock = filp->f_flags & O_NONBLOCK; @@ -642,7 +646,7 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) poll_wait(filp, &port->waitqueue, wait); ret = 0; - if (port->inbuf) + if (!will_read_block(port)) ret |= POLLIN | POLLRDNORM; if (!will_write_block(port)) ret |= POLLOUT; diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index c2408bb..f508690 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -80,7 +80,7 @@ * Limiting Performance Impact * --------------------------- * C states, especially those with large exit latencies, can have a real - * noticable impact on workloads, which is not acceptable for most sysadmins, + * noticeable impact on workloads, which is not acceptable for most sysadmins, * and in addition, less performance has a power price of its own. * * As a general rule of thumb, menu assumes that the following heuristic diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index 8661c84..b98c676 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -39,6 +39,10 @@ static DEFINE_SPINLOCK(dca_lock); static LIST_HEAD(dca_domains); +static BLOCKING_NOTIFIER_HEAD(dca_provider_chain); + +static int dca_providers_blocked; + static struct pci_bus *dca_pci_rc_from_dev(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -70,6 +74,60 @@ static void dca_free_domain(struct dca_domain *domain) kfree(domain); } +static int dca_provider_ioat_ver_3_0(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + return ((pdev->vendor == PCI_VENDOR_ID_INTEL) && + ((pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG0) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG1) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG2) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG3) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG4) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG5) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG6) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG7))); +} + +static void unregister_dca_providers(void) +{ + struct dca_provider *dca, *_dca; + struct list_head unregistered_providers; + struct dca_domain *domain; + unsigned long flags; + + blocking_notifier_call_chain(&dca_provider_chain, + DCA_PROVIDER_REMOVE, NULL); + + INIT_LIST_HEAD(&unregistered_providers); + + spin_lock_irqsave(&dca_lock, flags); + + if (list_empty(&dca_domains)) { + spin_unlock_irqrestore(&dca_lock, flags); + return; + } + + /* at this point only one domain in the list is expected */ + domain = list_first_entry(&dca_domains, struct dca_domain, node); + if (!domain) + return; + + list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) { + list_del(&dca->node); + list_add(&dca->node, &unregistered_providers); + } + + dca_free_domain(domain); + + spin_unlock_irqrestore(&dca_lock, flags); + + list_for_each_entry_safe(dca, _dca, &unregistered_providers, node) { + dca_sysfs_remove_provider(dca); + list_del(&dca->node); + } +} + static struct dca_domain *dca_find_domain(struct pci_bus *rc) { struct dca_domain *domain; @@ -90,9 +148,13 @@ static struct dca_domain *dca_get_domain(struct device *dev) domain = dca_find_domain(rc); if (!domain) { - domain = dca_allocate_domain(rc); - if (domain) - list_add(&domain->node, &dca_domains); + if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains)) { + dca_providers_blocked = 1; + } else { + domain = dca_allocate_domain(rc); + if (domain) + list_add(&domain->node, &dca_domains); + } } return domain; @@ -293,8 +355,6 @@ void free_dca_provider(struct dca_provider *dca) } EXPORT_SYMBOL_GPL(free_dca_provider); -static BLOCKING_NOTIFIER_HEAD(dca_provider_chain); - /** * register_dca_provider - register a dca provider * @dca - struct created by alloc_dca_provider() @@ -306,6 +366,13 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev) unsigned long flags; struct dca_domain *domain; + spin_lock_irqsave(&dca_lock, flags); + if (dca_providers_blocked) { + spin_unlock_irqrestore(&dca_lock, flags); + return -ENODEV; + } + spin_unlock_irqrestore(&dca_lock, flags); + err = dca_sysfs_add_provider(dca, dev); if (err) return err; @@ -313,7 +380,13 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev) spin_lock_irqsave(&dca_lock, flags); domain = dca_get_domain(dev); if (!domain) { - spin_unlock_irqrestore(&dca_lock, flags); + if (dca_providers_blocked) { + spin_unlock_irqrestore(&dca_lock, flags); + dca_sysfs_remove_provider(dca); + unregister_dca_providers(); + } else { + spin_unlock_irqrestore(&dca_lock, flags); + } return -ENODEV; } list_add(&dca->node, &domain->dca_providers); diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 216f9d3..effd140 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -879,7 +879,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) dma->device_issue_pending = ioat2_issue_pending; dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; dma->device_free_chan_resources = ioat2_free_chan_resources; - dma->device_tx_status = ioat_tx_status; + dma->device_tx_status = ioat_dma_tx_status; err = ioat_probe(device); if (err) diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 86c5ae9..411d5bf 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -162,7 +162,7 @@ static int mv_is_err_intr(u32 intr_cause) static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan) { - u32 val = (1 << (1 + (chan->idx * 16))); + u32 val = ~(1 << (chan->idx * 16)); dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val); __raw_writel(val, XOR_INTR_CAUSE(chan)); } diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index fb64cf3..eb6b54d 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -580,7 +580,6 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( sh_chan = to_sh_chan(chan); param = chan->private; - slave_addr = param->config->addr; /* Someone calling slave DMA on a public channel? */ if (!param || !sg_len) { @@ -589,6 +588,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( return NULL; } + slave_addr = param->config->addr; + /* * if (param != NULL), this is a successfully requested slave channel, * therefore param->config != NULL too. diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 3630308..6b21e25 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -339,6 +339,9 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) { int status; + if (mci->op_state != OP_RUNNING_POLL) + return; + status = cancel_delayed_work(&mci->work); if (status == 0) { debugf0("%s() not canceled, flush the queue\n", diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index e0187d1..0fd5b85 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1140,6 +1140,7 @@ static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = { ATTR_COUNTER(0), ATTR_COUNTER(1), ATTR_COUNTER(2), + { .attr = { .name = NULL } } }; static struct mcidev_sysfs_group i7core_udimm_counters = { diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index be29b0b..1b05896 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -263,6 +263,7 @@ static const struct { {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI}, {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_VIA, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, + {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS}, }; diff --git a/drivers/gpu/drm/drm_buffer.c b/drivers/gpu/drm/drm_buffer.c index 55d03ed..529a0db 100644 --- a/drivers/gpu/drm/drm_buffer.c +++ b/drivers/gpu/drm/drm_buffer.c @@ -98,8 +98,8 @@ EXPORT_SYMBOL(drm_buffer_alloc); * user_data: A pointer the data that is copied to the buffer. * size: The Number of bytes to copy. */ -extern int drm_buffer_copy_from_user(struct drm_buffer *buf, - void __user *user_data, int size) +int drm_buffer_copy_from_user(struct drm_buffer *buf, + void __user *user_data, int size) { int nr_pages = size / PAGE_SIZE + 1; int idx; @@ -163,7 +163,7 @@ void *drm_buffer_read_object(struct drm_buffer *buf, { int idx = drm_buffer_index(buf); int page = drm_buffer_page(buf); - void *obj = 0; + void *obj = NULL; if (idx + objsize <= PAGE_SIZE) { obj = &buf->data[page][idx]; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d2ab01e..dcbeb98 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -103,8 +103,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, if (connector->funcs->force) connector->funcs->force(connector); } else { - connector->status = connector->funcs->detect(connector); - drm_helper_hpd_irq_event(dev); + connector->status = connector->funcs->detect(connector, true); + drm_kms_helper_poll_enable(dev); } if (connector->status == connector_status_disconnected) { @@ -637,13 +637,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) mode_changed = true; if (mode_changed) { - old_fb = set->crtc->fb; - set->crtc->fb = set->fb; set->crtc->enabled = (set->mode != NULL); if (set->mode != NULL) { DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); + old_fb = set->crtc->fb; + set->crtc->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, set->y, old_fb)) { @@ -866,7 +866,7 @@ static void output_poll_execute(struct work_struct *work) !(connector->polled & DRM_CONNECTOR_POLL_HPD)) continue; - status = connector->funcs->detect(connector); + status = connector->funcs->detect(connector, false); if (old_status != status) changed = true; } diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index bf92d07..5663d27 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -148,7 +148,7 @@ int drm_gem_object_init(struct drm_device *dev, return -ENOMEM; kref_init(&obj->refcount); - kref_init(&obj->handlecount); + atomic_set(&obj->handle_count, 0); obj->size = size; atomic_inc(&dev->object_count); @@ -462,28 +462,6 @@ drm_gem_object_free(struct kref *kref) } EXPORT_SYMBOL(drm_gem_object_free); -/** - * Called after the last reference to the object has been lost. - * Must be called without holding struct_mutex - * - * Frees the object - */ -void -drm_gem_object_free_unlocked(struct kref *kref) -{ - struct drm_gem_object *obj = (struct drm_gem_object *) kref; - struct drm_device *dev = obj->dev; - - if (dev->driver->gem_free_object_unlocked != NULL) - dev->driver->gem_free_object_unlocked(obj); - else if (dev->driver->gem_free_object != NULL) { - mutex_lock(&dev->struct_mutex); - dev->driver->gem_free_object(obj); - mutex_unlock(&dev->struct_mutex); - } -} -EXPORT_SYMBOL(drm_gem_object_free_unlocked); - static void drm_gem_object_ref_bug(struct kref *list_kref) { BUG(); @@ -496,12 +474,8 @@ static void drm_gem_object_ref_bug(struct kref *list_kref) * called before drm_gem_object_free or we'll be touching * freed memory */ -void -drm_gem_object_handle_free(struct kref *kref) +void drm_gem_object_handle_free(struct drm_gem_object *obj) { - struct drm_gem_object *obj = container_of(kref, - struct drm_gem_object, - handlecount); struct drm_device *dev = obj->dev; /* Remove any name for this object */ @@ -528,6 +502,10 @@ void drm_gem_vm_open(struct vm_area_struct *vma) struct drm_gem_object *obj = vma->vm_private_data; drm_gem_object_reference(obj); + + mutex_lock(&obj->dev->struct_mutex); + drm_vm_open_locked(vma); + mutex_unlock(&obj->dev->struct_mutex); } EXPORT_SYMBOL(drm_gem_vm_open); @@ -535,7 +513,10 @@ void drm_gem_vm_close(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; - drm_gem_object_unreference_unlocked(obj); + mutex_lock(&obj->dev->struct_mutex); + drm_vm_close_locked(vma); + drm_gem_object_unreference(obj); + mutex_unlock(&obj->dev->struct_mutex); } EXPORT_SYMBOL(drm_gem_vm_close); diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 2ef2c78..974e970 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -255,7 +255,7 @@ int drm_gem_one_name_info(int id, void *ptr, void *data) seq_printf(m, "%6d %8zd %7d %8d\n", obj->name, obj->size, - atomic_read(&obj->handlecount.refcount), + atomic_read(&obj->handle_count), atomic_read(&obj->refcount.refcount)); return 0; } diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e20f78b..f5bd9e5 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, dev->hose = pdev->sysdata; #endif + mutex_lock(&drm_global_mutex); + if ((ret = drm_fill_in_dev(dev, ent, driver))) { printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); goto err_g2; @@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, pci_name(pdev), dev->primary->index); + mutex_unlock(&drm_global_mutex); return 0; err_g4: @@ -210,6 +213,7 @@ err_g2: pci_disable_device(pdev); err_g1: kfree(dev); + mutex_unlock(&drm_global_mutex); return ret; } EXPORT_SYMBOL(drm_get_pci_dev); diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 460e9a3..92d1d0f 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev, dev->platformdev = platdev; dev->dev = &platdev->dev; + mutex_lock(&drm_global_mutex); + ret = drm_fill_in_dev(dev, NULL, driver); if (ret) { @@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev, list_add_tail(&dev->driver_item, &driver->device_list); + mutex_unlock(&drm_global_mutex); + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); @@ -100,6 +104,7 @@ err_g2: drm_put_minor(&dev->control); err_g1: kfree(dev); + mutex_unlock(&drm_global_mutex); return ret; } EXPORT_SYMBOL(drm_get_platform_dev); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 86118a7..85da4c4 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device, struct drm_connector *connector = to_drm_connector(device); enum drm_connector_status status; - status = connector->funcs->detect(connector); + status = connector->funcs->detect(connector, true); return snprintf(buf, PAGE_SIZE, "%s\n", drm_get_connector_status_name(status)); } diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index fda6746..5df4506 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -433,15 +433,7 @@ static void drm_vm_open(struct vm_area_struct *vma) mutex_unlock(&dev->struct_mutex); } -/** - * \c close method for all virtual memory types. - * - * \param vma virtual memory area. - * - * Search the \p vma private data entry in drm_device::vmalist, unlink it, and - * free it. - */ -static void drm_vm_close(struct vm_area_struct *vma) +void drm_vm_close_locked(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->minor->dev; @@ -451,7 +443,6 @@ static void drm_vm_close(struct vm_area_struct *vma) vma->vm_start, vma->vm_end - vma->vm_start); atomic_dec(&dev->vma_count); - mutex_lock(&dev->struct_mutex); list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { if (pt->vma == vma) { list_del(&pt->head); @@ -459,6 +450,23 @@ static void drm_vm_close(struct vm_area_struct *vma) break; } } +} + +/** + * \c close method for all virtual memory types. + * + * \param vma virtual memory area. + * + * Search the \p vma private data entry in drm_device::vmalist, unlink it, and + * free it. + */ +static void drm_vm_close(struct vm_area_struct *vma) +{ + struct drm_file *priv = vma->vm_file->private_data; + struct drm_device *dev = priv->minor->dev; + + mutex_lock(&dev->struct_mutex); + drm_vm_close_locked(vma); mutex_unlock(&dev->struct_mutex); } diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 61b4caf..fb07e73 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -116,7 +116,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) static const struct file_operations i810_buffer_fops = { .open = drm_open, .release = drm_release, - .unlocked_ioctl = drm_ioctl, + .unlocked_ioctl = i810_ioctl, .mmap = i810_mmap_buffers, .fasync = drm_fasync, }; diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c index 671aa18..cc92c7e 100644 --- a/drivers/gpu/drm/i830/i830_dma.c +++ b/drivers/gpu/drm/i830/i830_dma.c @@ -118,7 +118,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) static const struct file_operations i830_buffer_fops = { .open = drm_open, .release = drm_release, - .unlocked_ioctl = drm_ioctl, + .unlocked_ioctl = i830_ioctl, .mmap = i830_mmap_buffers, .fasync = drm_fasync, }; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9d67b48..2dd2c93 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1787,9 +1787,9 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) } } - div_u64(diff, diff1); + diff = div_u64(diff, diff1); ret = ((m * diff) + c); - div_u64(ret, 10); + ret = div_u64(ret, 10); dev_priv->last_count1 = total_count; dev_priv->last_time1 = now; @@ -1858,7 +1858,7 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv) /* More magic constants... */ diff = diff * 1181; - div_u64(diff, diffms * 10); + diff = div_u64(diff, diffms * 10); dev_priv->gfx_power = diff; } @@ -2231,6 +2231,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->mchdev_lock = &mchdev_lock; spin_unlock(&mchdev_lock); + /* XXX Prevent module unload due to memory corruption bugs. */ + __module_get(THIS_MODULE); + return 0; out_workqueue_free: diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 216deb5..6dbe14c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -170,6 +170,7 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x2e22, &intel_g45_info), /* G45_G */ INTEL_VGA_DEVICE(0x2e32, &intel_g45_info), /* G41_G */ INTEL_VGA_DEVICE(0x2e42, &intel_g45_info), /* B43_G */ + INTEL_VGA_DEVICE(0x2e92, &intel_g45_info), /* B43_G.1 */ INTEL_VGA_DEVICE(0xa001, &intel_pineview_info), INTEL_VGA_DEVICE(0xa011, &intel_pineview_info), INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 16fca1d..90b1d67 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -136,14 +136,12 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, return -ENOMEM; ret = drm_gem_handle_create(file_priv, obj, &handle); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(obj); if (ret) { - drm_gem_object_unreference_unlocked(obj); return ret; } - /* Sink the floating reference from kref_init(handlecount) */ - drm_gem_object_handle_unreference_unlocked(obj); - args->handle = handle; return 0; } @@ -471,14 +469,17 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, return -ENOENT; obj_priv = to_intel_bo(obj); - /* Bounds check source. - * - * XXX: This could use review for overflow issues... - */ - if (args->offset > obj->size || args->size > obj->size || - args->offset + args->size > obj->size) { - drm_gem_object_unreference_unlocked(obj); - return -EINVAL; + /* Bounds check source. */ + if (args->offset > obj->size || args->size > obj->size - args->offset) { + ret = -EINVAL; + goto err; + } + + if (!access_ok(VERIFY_WRITE, + (char __user *)(uintptr_t)args->data_ptr, + args->size)) { + ret = -EFAULT; + goto err; } if (i915_gem_object_needs_bit17_swizzle(obj)) { @@ -490,8 +491,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, file_priv); } +err: drm_gem_object_unreference_unlocked(obj); - return ret; } @@ -580,8 +581,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, user_data = (char __user *) (uintptr_t) args->data_ptr; remain = args->size; - if (!access_ok(VERIFY_READ, user_data, remain)) - return -EFAULT; mutex_lock(&dev->struct_mutex); @@ -934,14 +933,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, return -ENOENT; obj_priv = to_intel_bo(obj); - /* Bounds check destination. - * - * XXX: This could use review for overflow issues... - */ - if (args->offset > obj->size || args->size > obj->size || - args->offset + args->size > obj->size) { - drm_gem_object_unreference_unlocked(obj); - return -EINVAL; + /* Bounds check destination. */ + if (args->offset > obj->size || args->size > obj->size - args->offset) { + ret = -EINVAL; + goto err; + } + + if (!access_ok(VERIFY_READ, + (char __user *)(uintptr_t)args->data_ptr, + args->size)) { + ret = -EFAULT; + goto err; } /* We can only do the GTT pwrite on untiled buffers, as otherwise @@ -975,8 +977,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, DRM_INFO("pwrite failed %d\n", ret); #endif +err: drm_gem_object_unreference_unlocked(obj); - return ret; } @@ -2351,14 +2353,21 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) reg->obj = obj; - if (IS_GEN6(dev)) + switch (INTEL_INFO(dev)->gen) { + case 6: sandybridge_write_fence_reg(reg); - else if (IS_I965G(dev)) + break; + case 5: + case 4: i965_write_fence_reg(reg); - else if (IS_I9XX(dev)) + break; + case 3: i915_write_fence_reg(reg); - else + break; + case 2: i830_write_fence_reg(reg); + break; + } trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg, obj_priv->tiling_mode); @@ -2381,22 +2390,26 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[obj_priv->fence_reg]; + uint32_t fence_reg; - if (IS_GEN6(dev)) { + switch (INTEL_INFO(dev)->gen) { + case 6: I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (obj_priv->fence_reg * 8), 0); - } else if (IS_I965G(dev)) { + break; + case 5: + case 4: I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); - } else { - uint32_t fence_reg; - - if (obj_priv->fence_reg < 8) - fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; + break; + case 3: + if (obj_priv->fence_reg >= 8) + fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 8) * 4; else - fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - - 8) * 4; + case 2: + fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; I915_WRITE(fence_reg, 0); + break; } reg->obj = NULL; @@ -3247,6 +3260,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, (int) reloc->offset, reloc->read_domains, reloc->write_domain); + drm_gem_object_unreference(target_obj); + i915_gem_object_unpin(obj); return -EINVAL; } if (reloc->write_domain & I915_GEM_DOMAIN_CPU || diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 72cae3c..5c428fa 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -79,6 +79,7 @@ mark_free(struct drm_i915_gem_object *obj_priv, struct list_head *unwind) { list_add(&obj_priv->evict_list, unwind); + drm_gem_object_reference(&obj_priv->base); return drm_mm_scan_add_block(obj_priv->gtt_space); } @@ -92,7 +93,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen { drm_i915_private_t *dev_priv = dev->dev_private; struct list_head eviction_list, unwind_list; - struct drm_i915_gem_object *obj_priv, *tmp_obj_priv; + struct drm_i915_gem_object *obj_priv; struct list_head *render_iter, *bsd_iter; int ret = 0; @@ -165,6 +166,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen list_for_each_entry(obj_priv, &unwind_list, evict_list) { ret = drm_mm_scan_remove_block(obj_priv->gtt_space); BUG_ON(ret); + drm_gem_object_unreference(&obj_priv->base); } /* We expect the caller to unpin, evict all and try again, or give up. @@ -173,36 +175,34 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen return -ENOSPC; found: + /* drm_mm doesn't allow any other other operations while + * scanning, therefore store to be evicted objects on a + * temporary list. */ INIT_LIST_HEAD(&eviction_list); - list_for_each_entry_safe(obj_priv, tmp_obj_priv, - &unwind_list, evict_list) { + while (!list_empty(&unwind_list)) { + obj_priv = list_first_entry(&unwind_list, + struct drm_i915_gem_object, + evict_list); if (drm_mm_scan_remove_block(obj_priv->gtt_space)) { - /* drm_mm doesn't allow any other other operations while - * scanning, therefore store to be evicted objects on a - * temporary list. */ list_move(&obj_priv->evict_list, &eviction_list); + continue; } + list_del(&obj_priv->evict_list); + drm_gem_object_unreference(&obj_priv->base); } /* Unbinding will emit any required flushes */ - list_for_each_entry_safe(obj_priv, tmp_obj_priv, - &eviction_list, evict_list) { -#if WATCH_LRU - DRM_INFO("%s: evicting %p\n", __func__, obj); -#endif - ret = i915_gem_object_unbind(&obj_priv->base); - if (ret) - return ret; + while (!list_empty(&eviction_list)) { + obj_priv = list_first_entry(&eviction_list, + struct drm_i915_gem_object, + evict_list); + if (ret == 0) + ret = i915_gem_object_unbind(&obj_priv->base); + list_del(&obj_priv->evict_list); + drm_gem_object_unreference(&obj_priv->base); } - /* The just created free hole should be on the top of the free stack - * maintained by drm_mm, so this BUG_ON actually executes in O(1). - * Furthermore all accessed data has just recently been used, so it - * should be really fast, too. */ - BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size, - alignment, 0)); - - return 0; + return ret; } int diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 2c6b98f..31f0858 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -789,16 +789,25 @@ int i915_save_state(struct drm_device *dev) dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); /* Fences */ - if (IS_I965G(dev)) { + switch (INTEL_INFO(dev)->gen) { + case 6: + for (i = 0; i < 16; i++) + dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); + break; + case 5: + case 4: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); - } else { - for (i = 0; i < 8; i++) - dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); - + break; + case 3: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); + case 2: + for (i = 0; i < 8; i++) + dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); + break; + } return 0; @@ -815,15 +824,24 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE(HWS_PGA, dev_priv->saveHWS); /* Fences */ - if (IS_I965G(dev)) { + switch (INTEL_INFO(dev)->gen) { + case 6: + for (i = 0; i < 16; i++) + I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); + break; + case 5: + case 4: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]); - } else { - for (i = 0; i < 8; i++) - I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); + break; + case 3: + case 2: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); + for (i = 0; i < 8; i++) + I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); + break; } i915_restore_display(dev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 4b77351..197d4f3 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -188,7 +188,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, 1000, 1)) - DRM_ERROR("timed out waiting for FORCE_TRIGGER"); + DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); if (turn_off_dac) { I915_WRITE(PCH_ADPA, temp); @@ -245,7 +245,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) if (wait_for((I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0, 1000, 1)) - DRM_ERROR("timed out waiting for FORCE_DETECT to go off"); + DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); } stat = I915_READ(PORT_HOTPLUG_STAT); @@ -400,7 +400,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder return status; } -static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_crt_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct drm_encoder *encoder = intel_attached_encoder(connector); @@ -419,6 +420,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto if (intel_crt_detect_ddc(encoder)) return connector_status_connected; + if (!force) + return connector->status; + /* for pre-945g platforms use load detect */ if (encoder->crtc && encoder->crtc->enabled) { status = intel_crt_load_detect(encoder->crtc, intel_encoder); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 19daead..9792285 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1013,8 +1013,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) DRM_DEBUG_KMS("vblank wait timed out\n"); } -/** - * intel_wait_for_vblank_off - wait for vblank after disabling a pipe +/* + * intel_wait_for_pipe_off - wait for pipe to turn off * @dev: drm device * @pipe: pipe to wait for * @@ -1022,25 +1022,39 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) * spinning on the vblank interrupt status bit, since we won't actually * see an interrupt when the pipe is disabled. * - * So this function waits for the display line value to settle (it - * usually ends up stopping at the start of the next frame). + * On Gen4 and above: + * wait for the pipe register state bit to turn off + * + * Otherwise: + * wait for the display line value to settle (it usually + * ends up stopping at the start of the next frame). + * */ -void intel_wait_for_vblank_off(struct drm_device *dev, int pipe) +static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); - unsigned long timeout = jiffies + msecs_to_jiffies(100); - u32 last_line; - - /* Wait for the display line to settle */ - do { - last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; - mdelay(5); - } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && - time_after(timeout, jiffies)); - - if (time_after(jiffies, timeout)) - DRM_DEBUG_KMS("vblank wait timed out\n"); + + if (INTEL_INFO(dev)->gen >= 4) { + int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF); + + /* Wait for the Pipe State to go off */ + if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, + 100, 0)) + DRM_DEBUG_KMS("pipe_off wait timed out\n"); + } else { + u32 last_line; + int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); + unsigned long timeout = jiffies + msecs_to_jiffies(100); + + /* Wait for the display line to settle */ + do { + last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; + mdelay(5); + } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && + time_after(timeout, jiffies)); + if (time_after(jiffies, timeout)) + DRM_DEBUG_KMS("pipe_off wait timed out\n"); + } } /* Parameters have changed, update FBC info */ @@ -2328,13 +2342,13 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(dspbase_reg); } - /* Wait for vblank for the disable to take effect */ - intel_wait_for_vblank_off(dev, pipe); - /* Don't disable pipe A or pipe A PLLs if needed */ if (pipeconf_reg == PIPEACONF && - (dev_priv->quirks & QUIRK_PIPEA_FORCE)) + (dev_priv->quirks & QUIRK_PIPEA_FORCE)) { + /* Wait for vblank for the disable to take effect */ + intel_wait_for_vblank(dev, pipe); goto skip_pipe_off; + } /* Next, disable display pipes */ temp = I915_READ(pipeconf_reg); @@ -2343,8 +2357,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(pipeconf_reg); } - /* Wait for vblank for the disable to take effect. */ - intel_wait_for_vblank_off(dev, pipe); + /* Wait for the pipe to turn off */ + intel_wait_for_pipe_off(dev, pipe); temp = I915_READ(dpll_reg); if ((temp & DPLL_VCO_ENABLE) != 0) { @@ -2463,11 +2477,19 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; + if (HAS_PCH_SPLIT(dev)) { /* FDI link clock is fixed at 2.7G */ if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4) return false; } + + /* XXX some encoders set the crtcinfo, others don't. + * Obviously we need some form of conflict resolution here... + */ + if (adjusted_mode->crtc_htotal == 0) + drm_mode_set_crtcinfo(adjusted_mode, 0); + return true; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 51d1429..9ab8708 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1138,18 +1138,14 @@ static bool intel_dp_set_link_train(struct intel_dp *intel_dp, uint32_t dp_reg_value, uint8_t dp_train_pat, - uint8_t train_set[4], - bool first) + uint8_t train_set[4]) { struct drm_device *dev = intel_dp->base.enc.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); int ret; I915_WRITE(intel_dp->output_reg, dp_reg_value); POSTING_READ(intel_dp->output_reg); - if (first) - intel_wait_for_vblank(dev, intel_crtc->pipe); intel_dp_aux_native_write_1(intel_dp, DP_TRAINING_PATTERN_SET, @@ -1174,10 +1170,15 @@ intel_dp_link_train(struct intel_dp *intel_dp) uint8_t voltage; bool clock_recovery = false; bool channel_eq = false; - bool first = true; int tries; u32 reg; uint32_t DP = intel_dp->DP; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); + + /* Enable output, wait for it to become active */ + I915_WRITE(intel_dp->output_reg, intel_dp->DP); + POSTING_READ(intel_dp->output_reg); + intel_wait_for_vblank(dev, intel_crtc->pipe); /* Write the link configuration data */ intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, @@ -1210,9 +1211,8 @@ intel_dp_link_train(struct intel_dp *intel_dp) reg = DP | DP_LINK_TRAIN_PAT_1; if (!intel_dp_set_link_train(intel_dp, reg, - DP_TRAINING_PATTERN_1, train_set, first)) + DP_TRAINING_PATTERN_1, train_set)) break; - first = false; /* Set training pattern 1 */ udelay(100); @@ -1266,8 +1266,7 @@ intel_dp_link_train(struct intel_dp *intel_dp) /* channel eq pattern */ if (!intel_dp_set_link_train(intel_dp, reg, - DP_TRAINING_PATTERN_2, train_set, - false)) + DP_TRAINING_PATTERN_2, train_set)) break; udelay(400); @@ -1386,7 +1385,7 @@ ironlake_dp_detect(struct drm_connector *connector) * \return false if DP port is disconnected. */ static enum drm_connector_status -intel_dp_detect(struct drm_connector *connector) +intel_dp_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ad312ca..8828b3a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -229,7 +229,6 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc); int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe); extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index a399f4b..7c9ec14 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -221,7 +221,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, * * Unimplemented. */ -static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_dvo_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 7bdc962..b61966c 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -237,8 +237,10 @@ int intel_fbdev_destroy(struct drm_device *dev, drm_fb_helper_fini(&ifbdev->helper); drm_framebuffer_cleanup(&ifb->base); - if (ifb->obj) + if (ifb->obj) { drm_gem_object_unreference(ifb->obj); + ifb->obj = NULL; + } return 0; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ccd4c97..926934a 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -139,7 +139,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, } static enum drm_connector_status -intel_hdmi_detect(struct drm_connector *connector) +intel_hdmi_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 4fbb016..6ec39a8 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -445,7 +445,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, * connected and closed means disconnected. We also send hotplug events as * needed, using lid status notification from the input layer. */ -static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_lvds_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; enum drm_connector_status status = connector_status_connected; @@ -540,7 +541,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, * the LID nofication event. */ if (connector) - connector->status = connector->funcs->detect(connector); + connector->status = connector->funcs->detect(connector, + false); + /* Don't force modeset on machines where it causes a GPU lockup */ if (dmi_check_system(intel_no_modeset_on_lid)) return NOTIFY_OK; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e3b7a7e..ee73e42 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1417,7 +1417,7 @@ intel_analog_is_connected(struct drm_device *dev) if (!analog_connector) return false; - if (analog_connector->funcs->detect(analog_connector) == + if (analog_connector->funcs->detect(analog_connector, false) == connector_status_disconnected) return false; @@ -1486,7 +1486,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) return status; } -static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_sdvo_detect(struct drm_connector *connector, bool force) { uint16_t response; struct drm_encoder *encoder = intel_attached_encoder(connector); @@ -2169,8 +2170,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) return true; err: - intel_sdvo_destroy_enhance_property(connector); - kfree(intel_sdvo_connector); + intel_sdvo_destroy(connector); return false; } @@ -2242,8 +2242,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) return true; err: - intel_sdvo_destroy_enhance_property(connector); - kfree(intel_sdvo_connector); + intel_sdvo_destroy(connector); return false; } @@ -2521,11 +2520,10 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, uint16_t response; } enhancements; - if (!intel_sdvo_get_value(intel_sdvo, - SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, - &enhancements, sizeof(enhancements))) - return false; - + enhancements.response = 0; + intel_sdvo_get_value(intel_sdvo, + SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, + &enhancements, sizeof(enhancements)); if (enhancements.response == 0) { DRM_DEBUG_KMS("No enhancement is supported\n"); return true; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index c671f60..4a117e3 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1341,7 +1341,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector) * we have a pipe programmed in order to probe the TV. */ static enum drm_connector_status -intel_tv_detect(struct drm_connector *connector) +intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct drm_encoder *encoder = intel_attached_encoder(connector); @@ -1353,7 +1353,7 @@ intel_tv_detect(struct drm_connector *connector) if (encoder->crtc && encoder->crtc->enabled) { type = intel_tv_detect_type(intel_tv); - } else { + } else if (force) { struct drm_crtc *crtc; int dpms_mode; @@ -1364,10 +1364,9 @@ intel_tv_detect(struct drm_connector *connector) intel_release_load_detect_pipe(&intel_tv->base, connector, dpms_mode); } else - type = -1; - } - - intel_tv->type = type; + return connector_status_unknown; + } else + return connector->status; if (type < 0) return connector_status_disconnected; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index a1473ff..fc73703 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -168,7 +168,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, } static enum drm_connector_status -nouveau_connector_detect(struct drm_connector *connector) +nouveau_connector_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct nouveau_connector *nv_connector = nouveau_connector(connector); @@ -246,7 +246,7 @@ detect_analog: } static enum drm_connector_status -nouveau_connector_detect_lvds(struct drm_connector *connector) +nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -267,7 +267,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector) /* Try retrieving EDID via DDC */ if (!dev_priv->vbios.fp_no_ddc) { - status = nouveau_connector_detect(connector); + status = nouveau_connector_detect(connector, force); if (status == connector_status_connected) goto out; } @@ -558,8 +558,10 @@ nouveau_connector_get_modes(struct drm_connector *connector) if (nv_encoder->dcb->type == OUTPUT_LVDS && (nv_encoder->dcb->lvdsconf.use_straps_for_mode || dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { - nv_connector->native_mode = drm_mode_create(dev); - nouveau_bios_fp_mode(dev, nv_connector->native_mode); + struct drm_display_mode mode; + + nouveau_bios_fp_mode(dev, &mode); + nv_connector->native_mode = drm_mode_duplicate(dev, &mode); } /* Find the native mode if this is a digital panel, if we didn't diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index ead7b8f..19620a6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -167,11 +167,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, goto out; ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(nvbo->gem); out: - drm_gem_object_handle_unreference_unlocked(nvbo->gem); - - if (ret) - drm_gem_object_unreference_unlocked(nvbo->gem); return ret; } diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 1bc72c3..fe359a2 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -4999,7 +4999,7 @@ typedef struct _SW_I2C_IO_DATA_PARAMETERS #define SW_I2C_CNTL_WRITE1BIT 6 //==============================VESA definition Portion=============================== -#define VESA_OEM_PRODUCT_REV '01.00' +#define VESA_OEM_PRODUCT_REV "01.00" #define VESA_MODE_ATTRIBUTE_MODE_SUPPORT 0xBB //refer to VBE spec p.32, no TTY support #define VESA_MODE_WIN_ATTRIBUTE 7 #define VESA_WIN_SIZE 64 diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 464a81a..cd0290f 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -539,14 +539,15 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, pll->algo = PLL_ALGO_LEGACY; pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; } - /* There is some evidence (often anecdotal) that RV515 LVDS + /* There is some evidence (often anecdotal) that RV515/RV620 LVDS * (on some boards at least) prefers the legacy algo. I'm not * sure whether this should handled generically or on a * case-by-case quirk basis. Both algos should work fine in the * majority of cases. */ if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && - (rdev->family == CHIP_RV515)) { + ((rdev->family == CHIP_RV515) || + (rdev->family == CHIP_RV620))) { /* allow the user to overrride just in case */ if (radeon_new_pll == 1) pll->algo = PLL_ALGO_NEW; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b8b7f01..2f93d46 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1137,7 +1137,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) WREG32(RCU_IND_INDEX, 0x203); efuse_straps_3 = RREG32(RCU_IND_DATA); - efuse_box_bit_127_124 = (u8)(efuse_straps_3 & 0xF0000000) >> 28; + efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28); switch(efuse_box_bit_127_124) { case 0x0: @@ -1160,14 +1160,25 @@ static void evergreen_gpu_init(struct radeon_device *rdev) EVERGREEN_MAX_BACKENDS_MASK)); break; } - } else - gb_backend_map = - evergreen_get_tile_pipe_to_backend_map(rdev, - rdev->config.evergreen.max_tile_pipes, - rdev->config.evergreen.max_backends, - ((EVERGREEN_MAX_BACKENDS_MASK << - rdev->config.evergreen.max_backends) & - EVERGREEN_MAX_BACKENDS_MASK)); + } else { + switch (rdev->family) { + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + gb_backend_map = 0x66442200; + break; + case CHIP_JUNIPER: + gb_backend_map = 0x00006420; + break; + default: + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + } + } rdev->config.evergreen.tile_config = gb_addr_config; WREG32(GB_BACKEND_MAP, gb_backend_map); @@ -1396,6 +1407,7 @@ int evergreen_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); @@ -1509,7 +1521,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) { u32 tmp; - WREG32(CP_INT_CNTL, 0); + WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); WREG32(GRBM_INT_CNTL, 0); WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index e817a0b..e594223 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1030,6 +1030,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) return r; } rdev->cp.ready = true; + rdev->mc.active_vram_size = rdev->mc.real_vram_size; return 0; } @@ -1047,6 +1048,7 @@ void r100_cp_fini(struct radeon_device *rdev) void r100_cp_disable(struct radeon_device *rdev) { /* Disable ring */ + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; rdev->cp.ready = false; WREG32(RADEON_CP_CSQ_MODE, 0); WREG32(RADEON_CP_CSQ_CNTL, 0); @@ -2020,18 +2022,7 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l return false; } elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); - if (elapsed >= 3000) { - /* very likely the improbable case where current - * rptr is equal to last recorded, a while ago, rptr - * this is more likely a false positive update tracking - * information which should force us to be recall at - * latter point - */ - lockup->last_cp_rptr = cp->rptr; - lockup->last_jiffies = jiffies; - return false; - } - if (elapsed >= 1000) { + if (elapsed >= 10000) { dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); return true; } @@ -2306,6 +2297,7 @@ void r100_vram_init_sizes(struct radeon_device *rdev) /* FIXME we don't use the second aperture yet when we could use it */ if (rdev->mc.visible_vram_size > rdev->mc.aper_size) rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); if (rdev->flags & RADEON_IS_IGP) { uint32_t tom; @@ -3308,13 +3300,14 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) unsigned long size; unsigned prim_walk; unsigned nverts; + unsigned num_cb = track->num_cb; - for (i = 0; i < track->num_cb; i++) { + if (!track->zb_cb_clear && !track->color_channel_mask && + !track->blend_read_enable) + num_cb = 0; + + for (i = 0; i < num_cb; i++) { if (track->cb[i].robj == NULL) { - if (!(track->zb_cb_clear || track->color_channel_mask || - track->blend_read_enable)) { - continue; - } DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); return -EINVAL; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index afc18d8..7b65e4ef 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1248,6 +1248,7 @@ int r600_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); if (rdev->flags & RADEON_IS_IGP) { @@ -1917,6 +1918,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) */ void r600_cp_stop(struct radeon_device *rdev) { + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); } @@ -2729,7 +2731,7 @@ int r600_ib_test(struct radeon_device *rdev) if (i < rdev->usec_timeout) { DRM_INFO("ib test succeeded in %u usecs\n", i); } else { - DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n", + DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", scratch, tmp); r = -EINVAL; } @@ -2910,7 +2912,7 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) { u32 tmp; - WREG32(CP_INT_CNTL, 0); + WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); WREG32(GRBM_INT_CNTL, 0); WREG32(DxMODE_INT_MASK, 0); if (ASIC_IS_DCE3(rdev)) { @@ -3528,7 +3530,8 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL */ - if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && + rdev->vram_scratch.ptr) { void __iomem *ptr = (void *)rdev->vram_scratch.ptr; u32 tmp; diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d13622a..3473c00 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -1,3 +1,28 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + #include "drmP.h" #include "drm.h" #include "radeon_drm.h" @@ -507,6 +532,7 @@ int r600_blit_init(struct radeon_device *rdev) memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4); radeon_bo_kunmap(rdev->r600_blit.shader_obj); radeon_bo_unreserve(rdev->r600_blit.shader_obj); + rdev->mc.active_vram_size = rdev->mc.real_vram_size; return 0; } @@ -514,6 +540,7 @@ void r600_blit_fini(struct radeon_device *rdev) { int r; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; if (rdev->r600_blit.shader_obj == NULL) return; /* If we can't reserve the bo, unref should be enough to destroy diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.h b/drivers/gpu/drm/radeon/r600_blit_shaders.h index fdc3b37..f437d36 100644 --- a/drivers/gpu/drm/radeon/r600_blit_shaders.h +++ b/drivers/gpu/drm/radeon/r600_blit_shaders.h @@ -1,3 +1,27 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ #ifndef R600_BLIT_SHADERS_H #define R600_BLIT_SHADERS_H diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index d886494..250a3a9 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -1170,9 +1170,8 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i /* using get ib will give us the offset into the mipmap bo */ word0 = radeon_get_ib_value(p, idx + 3) << 8; if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { - dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", - w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); - return -EINVAL; + /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", + w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ } return 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index a168d64..9ff38c9 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -344,6 +344,7 @@ struct radeon_mc { * about vram size near mc fb location */ u64 mc_vram_size; u64 visible_vram_size; + u64 active_vram_size; u64 gtt_size; u64 gtt_start; u64 gtt_end; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index ebae14c..8e43dda 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -317,6 +317,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, *connector_type = DRM_MODE_CONNECTOR_DVID; } + /* MSI K9A2GM V2/V3 board has no HDMI or DVI */ + if ((dev->pdev->device == 0x796e) && + (dev->pdev->subsystem_vendor == 0x1462) && + (dev->pdev->subsystem_device == 0x7302)) { + if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) || + (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) + return false; + } + /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ if ((dev->pdev->device == 0x7941) && (dev->pdev->subsystem_vendor == 0x147b) && @@ -1549,39 +1558,39 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev) switch (tv_info->ucTV_BootUpDefaultStandard) { case ATOM_TV_NTSC: tv_std = TV_STD_NTSC; - DRM_INFO("Default TV standard: NTSC\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC\n"); break; case ATOM_TV_NTSCJ: tv_std = TV_STD_NTSC_J; - DRM_INFO("Default TV standard: NTSC-J\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); break; case ATOM_TV_PAL: tv_std = TV_STD_PAL; - DRM_INFO("Default TV standard: PAL\n"); + DRM_DEBUG_KMS("Default TV standard: PAL\n"); break; case ATOM_TV_PALM: tv_std = TV_STD_PAL_M; - DRM_INFO("Default TV standard: PAL-M\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); break; case ATOM_TV_PALN: tv_std = TV_STD_PAL_N; - DRM_INFO("Default TV standard: PAL-N\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-N\n"); break; case ATOM_TV_PALCN: tv_std = TV_STD_PAL_CN; - DRM_INFO("Default TV standard: PAL-CN\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-CN\n"); break; case ATOM_TV_PAL60: tv_std = TV_STD_PAL_60; - DRM_INFO("Default TV standard: PAL-60\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); break; case ATOM_TV_SECAM: tv_std = TV_STD_SECAM; - DRM_INFO("Default TV standard: SECAM\n"); + DRM_DEBUG_KMS("Default TV standard: SECAM\n"); break; default: tv_std = TV_STD_NTSC; - DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); + DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n"); break; } } diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index bd74e42..7b7ea26 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -913,47 +913,47 @@ radeon_combios_get_tv_info(struct radeon_device *rdev) switch (RBIOS8(tv_info + 7) & 0xf) { case 1: tv_std = TV_STD_NTSC; - DRM_INFO("Default TV standard: NTSC\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC\n"); break; case 2: tv_std = TV_STD_PAL; - DRM_INFO("Default TV standard: PAL\n"); + DRM_DEBUG_KMS("Default TV standard: PAL\n"); break; case 3: tv_std = TV_STD_PAL_M; - DRM_INFO("Default TV standard: PAL-M\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); break; case 4: tv_std = TV_STD_PAL_60; - DRM_INFO("Default TV standard: PAL-60\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); break; case 5: tv_std = TV_STD_NTSC_J; - DRM_INFO("Default TV standard: NTSC-J\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); break; case 6: tv_std = TV_STD_SCART_PAL; - DRM_INFO("Default TV standard: SCART-PAL\n"); + DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n"); break; default: tv_std = TV_STD_NTSC; - DRM_INFO + DRM_DEBUG_KMS ("Unknown TV standard; defaulting to NTSC\n"); break; } switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) { case 0: - DRM_INFO("29.498928713 MHz TV ref clk\n"); + DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n"); break; case 1: - DRM_INFO("28.636360000 MHz TV ref clk\n"); + DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n"); break; case 2: - DRM_INFO("14.318180000 MHz TV ref clk\n"); + DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n"); break; case 3: - DRM_INFO("27.000000000 MHz TV ref clk\n"); + DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n"); break; default: break; @@ -1324,7 +1324,7 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, if (tmds_info) { ver = RBIOS8(tmds_info); - DRM_INFO("DFP table revision: %d\n", ver); + DRM_DEBUG_KMS("DFP table revision: %d\n", ver); if (ver == 3) { n = RBIOS8(tmds_info + 5) + 1; if (n > 4) @@ -1408,7 +1408,7 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); if (offset) { ver = RBIOS8(offset); - DRM_INFO("External TMDS Table revision: %d\n", ver); + DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver); tmds->slave_addr = RBIOS8(offset + 4 + 2); tmds->slave_addr >>= 1; /* 7 bit addressing */ gpio = RBIOS8(offset + 4 + 3); @@ -1485,6 +1485,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) /* PowerMac8,1 ? */ /* imac g5 isight */ rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; + } else if ((rdev->pdev->device == 0x4a48) && + (rdev->pdev->subsystem_vendor == 0x1002) && + (rdev->pdev->subsystem_device == 0x4a48)) { + /* Mac X800 */ + rdev->mode_info.connector_table = CT_MAC_X800; } else #endif /* CONFIG_PPC_PMAC */ #ifdef CONFIG_PPC64 @@ -1961,6 +1966,48 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_VGA, &hpd); break; + case CT_MAC_X800: + DRM_INFO("Connector Table: %d (mac x800)\n", + rdev->mode_info.connector_table); + /* DVI - primary dac, internal tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* DVI - tv dac, dvo */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + hpd.hpd = RADEON_HPD_2; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP2_SUPPORT, + 0), + ATOM_DEVICE_DFP2_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP2_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, + &hpd); + break; default: DRM_INFO("Connector table: %d (invalid)\n", rdev->mode_info.connector_table); diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index a9dd784..ecc1a8f 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -481,7 +481,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, return MODE_OK; } -static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_lvds_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder = radeon_best_single_encoder(connector); @@ -594,7 +595,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector, return MODE_OK; } -static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_vga_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder; @@ -691,7 +693,8 @@ static int radeon_tv_mode_valid(struct drm_connector *connector, return MODE_OK; } -static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_tv_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder; struct drm_encoder_helper_funcs *encoder_funcs; @@ -748,7 +751,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector) * we have to check if this analog encoder is shared with anyone else (TV) * if its shared we have to set the other connector to disconnected. */ -static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_dvi_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder = NULL; @@ -972,7 +976,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) return ret; } -static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_dp_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); enum drm_connector_status ret = connector_status_disconnected; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 6dd434a..b92d2f2 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -349,6 +349,8 @@ static void radeon_print_display_setup(struct drm_device *dev) DRM_INFO(" DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_DFP5_SUPPORT) DRM_INFO(" DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP6_SUPPORT) + DRM_INFO(" DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_TV1_SUPPORT) DRM_INFO(" TV1: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_CV_SUPPORT) @@ -841,8 +843,9 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); - if (radeon_fb->obj) + if (radeon_fb->obj) { drm_gem_object_unreference_unlocked(radeon_fb->obj); + } drm_framebuffer_cleanup(fb); kfree(radeon_fb); } @@ -1140,17 +1143,18 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, radeon_crtc->rmx_type = radeon_encoder->rmx_type; else radeon_crtc->rmx_type = RMX_OFF; - src_v = crtc->mode.vdisplay; - dst_v = radeon_crtc->native_mode.vdisplay; - src_h = crtc->mode.hdisplay; - dst_h = radeon_crtc->native_mode.vdisplay; /* copy native mode */ memcpy(&radeon_crtc->native_mode, &radeon_encoder->native_mode, sizeof(struct drm_display_mode)); + src_v = crtc->mode.vdisplay; + dst_v = radeon_crtc->native_mode.vdisplay; + src_h = crtc->mode.hdisplay; + dst_h = radeon_crtc->native_mode.hdisplay; /* fix up for overscan on hdmi */ if (ASIC_IS_AVIVO(rdev) && + (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) && ((radeon_encoder->underscan_type == UNDERSCAN_ON) || ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && drm_detect_hdmi_monitor(radeon_connector->edid) && diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index c74a8b2..40b0c08 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -94,6 +94,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) ret = radeon_bo_reserve(rbo, false); if (likely(ret == 0)) { radeon_bo_kunmap(rbo); + radeon_bo_unpin(rbo); radeon_bo_unreserve(rbo); } drm_gem_object_unreference_unlocked(gobj); @@ -325,8 +326,6 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb { struct fb_info *info; struct radeon_framebuffer *rfb = &rfbdev->rfb; - struct radeon_bo *rbo; - int r; if (rfbdev->helper.fbdev) { info = rfbdev->helper.fbdev; @@ -338,14 +337,8 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb } if (rfb->obj) { - rbo = rfb->obj->driver_private; - r = radeon_bo_reserve(rbo, false); - if (likely(r == 0)) { - radeon_bo_kunmap(rbo); - radeon_bo_unpin(rbo); - radeon_bo_unreserve(rbo); - } - drm_gem_object_unreference_unlocked(rfb->obj); + radeonfb_destroy_pinned_object(rfb->obj); + rfb->obj = NULL; } drm_fb_helper_fini(&rfbdev->helper); drm_framebuffer_cleanup(&rfb->base); diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index c578f26..d1e595d 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -201,11 +201,11 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, return r; } r = drm_gem_handle_create(filp, gobj, &handle); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(gobj); if (r) { - drm_gem_object_unreference_unlocked(gobj); return r; } - drm_gem_object_handle_unreference_unlocked(gobj); args->handle = handle; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 5eee3c4..8fbbe1c 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -203,6 +203,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) */ int radeon_driver_firstopen_kms(struct drm_device *dev) { + struct radeon_device *rdev = dev->dev_private; + + if (rdev->powered_down) + return -EINVAL; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index efbe975..17a6602 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -204,7 +204,7 @@ struct radeon_i2c_chan { /* mostly for macs, but really any system without connector tables */ enum radeon_connector_table { - CT_NONE, + CT_NONE = 0, CT_GENERIC, CT_IBOOK, CT_POWERBOOK_EXTERNAL, @@ -215,6 +215,7 @@ enum radeon_connector_table { CT_IMAC_G5_ISIGHT, CT_EMAC, CT_RN50_POWER, + CT_MAC_X800, }; enum radeon_dvo_chip { diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 0afd1e6..b3b5306 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) u32 c = 0; rbo->placement.fpfn = 0; - rbo->placement.lpfn = 0; + rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT; rbo->placement.placement = rbo->placements; rbo->placement.busy_placement = rbo->placements; if (domain & RADEON_GEM_DOMAIN_VRAM) diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 353998d..3481bc7 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -124,11 +124,8 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, int r; r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); - if (unlikely(r != 0)) { - if (r != -ERESTARTSYS) - dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo); + if (unlikely(r != 0)) return r; - } spin_lock(&bo->tbo.lock); if (mem_type) *mem_type = bo->tbo.mem.mem_type; diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index cc05b23..51d5f7b 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -693,6 +693,7 @@ void rs600_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); base = RREG32_MC(R_000004_MC_FB_LOCATION); base = G_000004_MC_FB_START(base) << 16; diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 3e3f757..4dc2a87 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -157,6 +157,7 @@ void rs690_mc_init(struct radeon_device *rdev) rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index bfa59db..9490da7 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -267,6 +267,7 @@ static void rv770_mc_program(struct radeon_device *rdev) */ void r700_cp_stop(struct radeon_device *rdev) { + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); } @@ -992,6 +993,7 @@ int rv770_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index cb4cf7e..db809e0 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -442,6 +442,43 @@ out_err: } /** + * Call bo::reserved and with the lru lock held. + * Will release GPU memory type usage on destruction. + * This is the place to put in driver specific hooks. + * Will release the bo::reserved lock and the + * lru lock on exit. + */ + +static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) +{ + struct ttm_bo_global *glob = bo->glob; + + if (bo->ttm) { + + /** + * Release the lru_lock, since we don't want to have + * an atomic requirement on ttm_tt[unbind|destroy]. + */ + + spin_unlock(&glob->lru_lock); + ttm_tt_unbind(bo->ttm); + ttm_tt_destroy(bo->ttm); + bo->ttm = NULL; + spin_lock(&glob->lru_lock); + } + + if (bo->mem.mm_node) { + drm_mm_put_block(bo->mem.mm_node); + bo->mem.mm_node = NULL; + } + + atomic_set(&bo->reserved, 0); + wake_up_all(&bo->event_queue); + spin_unlock(&glob->lru_lock); +} + + +/** * If bo idle, remove from delayed- and lru lists, and unref. * If not idle, and already on delayed list, do nothing. * If not idle, and not on delayed list, put on delayed list, @@ -456,6 +493,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) int ret; spin_lock(&bo->lock); +retry: (void) ttm_bo_wait(bo, false, false, !remove_all); if (!bo->sync_obj) { @@ -464,31 +502,52 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) spin_unlock(&bo->lock); spin_lock(&glob->lru_lock); - put_count = ttm_bo_del_from_lru(bo); + ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0); + + /** + * Someone else has the object reserved. Bail and retry. + */ - ret = ttm_bo_reserve_locked(bo, false, false, false, 0); - BUG_ON(ret); - if (bo->ttm) - ttm_tt_unbind(bo->ttm); + if (unlikely(ret == -EBUSY)) { + spin_unlock(&glob->lru_lock); + spin_lock(&bo->lock); + goto requeue; + } + + /** + * We can re-check for sync object without taking + * the bo::lock since setting the sync object requires + * also bo::reserved. A busy object at this point may + * be caused by another thread starting an accelerated + * eviction. + */ + + if (unlikely(bo->sync_obj)) { + atomic_set(&bo->reserved, 0); + wake_up_all(&bo->event_queue); + spin_unlock(&glob->lru_lock); + spin_lock(&bo->lock); + if (remove_all) + goto retry; + else + goto requeue; + } + + put_count = ttm_bo_del_from_lru(bo); if (!list_empty(&bo->ddestroy)) { list_del_init(&bo->ddestroy); ++put_count; } - if (bo->mem.mm_node) { - drm_mm_put_block(bo->mem.mm_node); - bo->mem.mm_node = NULL; - } - spin_unlock(&glob->lru_lock); - atomic_set(&bo->reserved, 0); + ttm_bo_cleanup_memtype_use(bo); while (put_count--) kref_put(&bo->list_kref, ttm_bo_ref_bug); return 0; } - +requeue: spin_lock(&glob->lru_lock); if (list_empty(&bo->ddestroy)) { void *sync_obj = bo->sync_obj; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 7cffb3e..3451a82 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -351,6 +351,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, INIT_LIST_HEAD(&fbo->lru); INIT_LIST_HEAD(&fbo->swap); fbo->vm_node = NULL; + atomic_set(&fbo->cpu_writers, 0); fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); kref_init(&fbo->list_kref); diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index ca90479..b1e02ff 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -69,7 +69,7 @@ struct ttm_page_pool { spinlock_t lock; bool fill_lock; struct list_head list; - int gfp_flags; + gfp_t gfp_flags; unsigned npages; char *name; unsigned long nfrees; @@ -475,7 +475,7 @@ static void ttm_handle_caching_state_failure(struct list_head *pages, * This function is reentrant if caller updates count depending on number of * pages returned in pages array. */ -static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags, +static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, int ttm_flags, enum ttm_caching_state cstate, unsigned count) { struct page **caching_array; @@ -666,7 +666,7 @@ int ttm_get_pages(struct list_head *pages, int flags, { struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); struct page *p = NULL; - int gfp_flags = GFP_USER; + gfp_t gfp_flags = GFP_USER; int r; /* set zero flag for page allocation if required */ @@ -818,7 +818,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) return 0; } -void ttm_page_alloc_fini() +void ttm_page_alloc_fini(void) { int i; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 72ec2e2..a96ed6d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -148,13 +148,16 @@ static struct pci_device_id vmw_pci_id_list[] = { {0, 0, 0} }; -static char *vmw_devname = "vmwgfx"; +static int enable_fbdev; static int vmw_probe(struct pci_dev *, const struct pci_device_id *); static void vmw_master_init(struct vmw_master *); static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, void *ptr); +MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); +module_param_named(enable_fbdev, enable_fbdev, int, 0600); + static void vmw_print_capabilities(uint32_t capabilities) { DRM_INFO("Capabilities:\n"); @@ -192,8 +195,6 @@ static int vmw_request_device(struct vmw_private *dev_priv) { int ret; - vmw_kms_save_vga(dev_priv); - ret = vmw_fifo_init(dev_priv, &dev_priv->fifo); if (unlikely(ret != 0)) { DRM_ERROR("Unable to initialize FIFO.\n"); @@ -206,9 +207,35 @@ static int vmw_request_device(struct vmw_private *dev_priv) static void vmw_release_device(struct vmw_private *dev_priv) { vmw_fifo_release(dev_priv, &dev_priv->fifo); - vmw_kms_restore_vga(dev_priv); } +int vmw_3d_resource_inc(struct vmw_private *dev_priv) +{ + int ret = 0; + + mutex_lock(&dev_priv->release_mutex); + if (unlikely(dev_priv->num_3d_resources++ == 0)) { + ret = vmw_request_device(dev_priv); + if (unlikely(ret != 0)) + --dev_priv->num_3d_resources; + } + mutex_unlock(&dev_priv->release_mutex); + return ret; +} + + +void vmw_3d_resource_dec(struct vmw_private *dev_priv) +{ + int32_t n3d; + + mutex_lock(&dev_priv->release_mutex); + if (unlikely(--dev_priv->num_3d_resources == 0)) + vmw_release_device(dev_priv); + n3d = (int32_t) dev_priv->num_3d_resources; + mutex_unlock(&dev_priv->release_mutex); + + BUG_ON(n3d < 0); +} static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) { @@ -228,6 +255,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->last_read_sequence = (uint32_t) -100; mutex_init(&dev_priv->hw_mutex); mutex_init(&dev_priv->cmdbuf_mutex); + mutex_init(&dev_priv->release_mutex); rwlock_init(&dev_priv->resource_lock); idr_init(&dev_priv->context_idr); idr_init(&dev_priv->surface_idr); @@ -244,6 +272,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->vram_start = pci_resource_start(dev->pdev, 1); dev_priv->mmio_start = pci_resource_start(dev->pdev, 2); + dev_priv->enable_fb = enable_fbdev; + mutex_lock(&dev_priv->hw_mutex); vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); @@ -343,17 +373,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev->dev_private = dev_priv; - if (!dev->devname) - dev->devname = vmw_devname; - - if (dev_priv->capabilities & SVGA_CAP_IRQMASK) { - ret = drm_irq_install(dev); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed installing irq: %d\n", ret); - goto out_no_irq; - } - } - ret = pci_request_regions(dev->pdev, "vmwgfx probe"); dev_priv->stealth = (ret != 0); if (dev_priv->stealth) { @@ -369,26 +388,52 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) goto out_no_device; } } - ret = vmw_request_device(dev_priv); + ret = vmw_kms_init(dev_priv); if (unlikely(ret != 0)) - goto out_no_device; - vmw_kms_init(dev_priv); + goto out_no_kms; vmw_overlay_init(dev_priv); - vmw_fb_init(dev_priv); + if (dev_priv->enable_fb) { + ret = vmw_3d_resource_inc(dev_priv); + if (unlikely(ret != 0)) + goto out_no_fifo; + vmw_kms_save_vga(dev_priv); + vmw_fb_init(dev_priv); + DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? + "Detected device 3D availability.\n" : + "Detected no device 3D availability.\n"); + } else { + DRM_INFO("Delayed 3D detection since we're not " + "running the device in SVGA mode yet.\n"); + } + + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) { + ret = drm_irq_install(dev); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed installing irq: %d\n", ret); + goto out_no_irq; + } + } dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; register_pm_notifier(&dev_priv->pm_nb); - DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n"); - return 0; -out_no_device: - if (dev_priv->capabilities & SVGA_CAP_IRQMASK) - drm_irq_uninstall(dev_priv->dev); - if (dev->devname == vmw_devname) - dev->devname = NULL; out_no_irq: + if (dev_priv->enable_fb) { + vmw_fb_close(dev_priv); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } +out_no_fifo: + vmw_overlay_close(dev_priv); + vmw_kms_close(dev_priv); +out_no_kms: + if (dev_priv->stealth) + pci_release_region(dev->pdev, 2); + else + pci_release_regions(dev->pdev); +out_no_device: ttm_object_device_release(&dev_priv->tdev); out_err4: iounmap(dev_priv->mmio_virt); @@ -415,19 +460,20 @@ static int vmw_driver_unload(struct drm_device *dev) unregister_pm_notifier(&dev_priv->pm_nb); - vmw_fb_close(dev_priv); + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) + drm_irq_uninstall(dev_priv->dev); + if (dev_priv->enable_fb) { + vmw_fb_close(dev_priv); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } vmw_kms_close(dev_priv); vmw_overlay_close(dev_priv); - vmw_release_device(dev_priv); if (dev_priv->stealth) pci_release_region(dev->pdev, 2); else pci_release_regions(dev->pdev); - if (dev_priv->capabilities & SVGA_CAP_IRQMASK) - drm_irq_uninstall(dev_priv->dev); - if (dev->devname == vmw_devname) - dev->devname = NULL; ttm_object_device_release(&dev_priv->tdev); iounmap(dev_priv->mmio_virt); drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start, @@ -500,7 +546,7 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd, struct drm_ioctl_desc *ioctl = &vmw_ioctls[nr - DRM_COMMAND_BASE]; - if (unlikely(ioctl->cmd != cmd)) { + if (unlikely(ioctl->cmd_drv != cmd)) { DRM_ERROR("Invalid command format, ioctl %d\n", nr - DRM_COMMAND_BASE); return -EINVAL; @@ -589,6 +635,16 @@ static int vmw_master_set(struct drm_device *dev, struct vmw_master *vmaster = vmw_master(file_priv->master); int ret = 0; + if (!dev_priv->enable_fb) { + ret = vmw_3d_resource_inc(dev_priv); + if (unlikely(ret != 0)) + return ret; + vmw_kms_save_vga(dev_priv); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_TRACES, 0); + mutex_unlock(&dev_priv->hw_mutex); + } + if (active) { BUG_ON(active != &dev_priv->fbdev_master); ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile); @@ -617,7 +673,13 @@ static int vmw_master_set(struct drm_device *dev, return 0; out_no_active_lock: - vmw_release_device(dev_priv); + if (!dev_priv->enable_fb) { + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_TRACES, 1); + mutex_unlock(&dev_priv->hw_mutex); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } return ret; } @@ -645,11 +707,23 @@ static void vmw_master_drop(struct drm_device *dev, ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); + if (!dev_priv->enable_fb) { + ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM); + if (unlikely(ret != 0)) + DRM_ERROR("Unable to clean VRAM on master drop.\n"); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_TRACES, 1); + mutex_unlock(&dev_priv->hw_mutex); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } + dev_priv->active_master = &dev_priv->fbdev_master; ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM); ttm_vt_unlock(&dev_priv->fbdev_master.lock); - vmw_fb_on(dev_priv); + if (dev_priv->enable_fb) + vmw_fb_on(dev_priv); } @@ -722,6 +796,7 @@ static struct drm_driver driver = { .irq_postinstall = vmw_irq_postinstall, .irq_uninstall = vmw_irq_uninstall, .irq_handler = vmw_irq_handler, + .get_vblank_counter = vmw_get_vblank_counter, .reclaim_buffers_locked = NULL, .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 429f917..58de639 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -277,6 +277,7 @@ struct vmw_private { bool stealth; bool is_opened; + bool enable_fb; /** * Master management. @@ -285,6 +286,9 @@ struct vmw_private { struct vmw_master *active_master; struct vmw_master fbdev_master; struct notifier_block pm_nb; + + struct mutex release_mutex; + uint32_t num_3d_resources; }; static inline struct vmw_private *vmw_priv(struct drm_device *dev) @@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv, return val; } +int vmw_3d_resource_inc(struct vmw_private *dev_priv); +void vmw_3d_resource_dec(struct vmw_private *dev_priv); + /** * GMR utilities - vmwgfx_gmr.c */ @@ -511,6 +518,7 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv, unsigned bbp, unsigned depth); int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); /** * Overlay control - vmwgfx_overlay.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 870967a..409e172 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -615,6 +615,11 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, if (unlikely(ret != 0)) goto err_unlock; + if (bo->mem.mem_type == TTM_PL_VRAM && + bo->mem.mm_node->start < bo->num_pages) + (void) ttm_bo_validate(bo, &vmw_sys_placement, false, + false, false); + ret = ttm_bo_validate(bo, &ne_placement, false, false, false); /* Could probably bug on */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index e6a1eb7..0fe3176 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) mutex_lock(&dev_priv->hw_mutex); dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); + dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES); vmw_write(dev_priv, SVGA_REG_ENABLE, 1); min = 4; @@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) dev_priv->config_done_state); vmw_write(dev_priv, SVGA_REG_ENABLE, dev_priv->enable_state); + vmw_write(dev_priv, SVGA_REG_TRACES, + dev_priv->traces_state); mutex_unlock(&dev_priv->hw_mutex); vmw_fence_queue_takedown(&fifo->fence_queue); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 64d7f47..e882ba0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv) save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH); save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); + if (i == 0 && vmw_priv->num_displays == 1 && + save->width == 0 && save->height == 0) { + + /* + * It should be fairly safe to assume that these + * values are uninitialized. + */ + + save->width = vmw_priv->vga_width - save->pos_x; + save->height = vmw_priv->vga_height - save->pos_y; + } } + return 0; } @@ -984,3 +996,8 @@ out_unlock: ttm_read_unlock(&vmaster->lock); return ret; } + +u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) +{ + return 0; +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 2ff5cf7..11cb39e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -27,6 +27,8 @@ #include "vmwgfx_kms.h" +#define VMWGFX_LDU_NUM_DU 8 + #define vmw_crtc_to_ldu(x) \ container_of(x, struct vmw_legacy_display_unit, base.crtc) #define vmw_encoder_to_ldu(x) \ @@ -335,7 +337,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector) } static enum drm_connector_status - vmw_ldu_connector_detect(struct drm_connector *connector) + vmw_ldu_connector_detect(struct drm_connector *connector, + bool force) { if (vmw_connector_to_ldu(connector)->pref_active) return connector_status_connected; @@ -516,7 +519,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, DRM_MODE_CONNECTOR_LVDS); - connector->status = vmw_ldu_connector_detect(connector); + connector->status = vmw_ldu_connector_detect(connector, true); drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, DRM_MODE_ENCODER_LVDS); @@ -535,6 +538,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; + int i; + int ret; + if (dev_priv->ldu_priv) { DRM_INFO("ldu system already on\n"); return -EINVAL; @@ -552,23 +559,24 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) drm_mode_create_dirty_info_property(dev_priv->dev); - vmw_ldu_init(dev_priv, 0); - /* for old hardware without multimon only enable one display */ if (dev_priv->capabilities & SVGA_CAP_MULTIMON) { - vmw_ldu_init(dev_priv, 1); - vmw_ldu_init(dev_priv, 2); - vmw_ldu_init(dev_priv, 3); - vmw_ldu_init(dev_priv, 4); - vmw_ldu_init(dev_priv, 5); - vmw_ldu_init(dev_priv, 6); - vmw_ldu_init(dev_priv, 7); + for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i) + vmw_ldu_init(dev_priv, i); + ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU); + } else { + /* for old hardware without multimon only enable one display */ + vmw_ldu_init(dev_priv, 0); + ret = drm_vblank_init(dev, 1); } - return 0; + return ret; } int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; + + drm_vblank_cleanup(dev); if (!dev_priv->ldu_priv) return -ENOSYS; @@ -610,7 +618,7 @@ int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num, ldu->pref_height = 600; ldu->pref_active = false; } - con->status = vmw_ldu_connector_detect(con); + con->status = vmw_ldu_connector_detect(con, true); } mutex_unlock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 5f2d5df..c8c40e9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res) cmd->body.cid = cpu_to_le32(res->id); vmw_fifo_commit(dev_priv, sizeof(*cmd)); + vmw_3d_resource_dec(dev_priv); } static int vmw_context_init(struct vmw_private *dev_priv, @@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv, cmd->body.cid = cpu_to_le32(res->id); vmw_fifo_commit(dev_priv, sizeof(*cmd)); + (void) vmw_3d_resource_inc(dev_priv); vmw_resource_activate(res, vmw_hw_context_destroy); return 0; } @@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res) cmd->body.sid = cpu_to_le32(res->id); vmw_fifo_commit(dev_priv, sizeof(*cmd)); + vmw_3d_resource_dec(dev_priv); } void vmw_surface_res_free(struct vmw_resource *res) @@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv, } vmw_fifo_commit(dev_priv, submit_size); + (void) vmw_3d_resource_inc(dev_priv); vmw_resource_activate(res, vmw_hw_surface_destroy); return 0; } diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index b87569e..f366f96 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -598,7 +598,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev, pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count); } -void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace) +static void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace) { struct vga_device *vgadev; unsigned long flags; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0c52899..3f72924 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1285,8 +1285,11 @@ static const struct hid_device_id hid_blacklist[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, @@ -1578,7 +1581,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)}, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 85c6d13..765a4f5 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -105,6 +105,7 @@ #define USB_VENDOR_ID_ASUS 0x0486 #define USB_DEVICE_ID_ASUS_T91MT 0x0185 +#define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186 #define USB_VENDOR_ID_ASUSTEK 0x0b05 #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 @@ -128,6 +129,7 @@ #define USB_VENDOR_ID_BTC 0x046e #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 +#define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 #define USB_VENDOR_ID_CANDO 0x2087 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 @@ -149,6 +151,7 @@ #define USB_VENDOR_ID_CHICONY 0x04f2 #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 +#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_VENDOR_ID_CIDC 0x1677 @@ -507,6 +510,7 @@ #define USB_VENDOR_ID_UCLOGIC 0x5543 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 +#define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 #define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c index e91437c..ac5421d 100644 --- a/drivers/hid/hid-mosart.c +++ b/drivers/hid/hid-mosart.c @@ -239,6 +239,7 @@ static void mosart_remove(struct hid_device *hdev) static const struct hid_device_id mosart_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, { } }; MODULE_DEVICE_TABLE(hid, mosart_devices); diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 5771f85..956ed9a 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c @@ -64,6 +64,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, static const struct hid_device_id ts_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, { } }; diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b729c02..599041a 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -828,6 +828,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co } } else { int skipped_report_id = 0; + int report_id = buf[0]; if (buf[0] == 0x0) { /* Don't send the Report ID */ buf++; @@ -837,7 +838,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), HID_REQ_SET_REPORT, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | *buf, + ((report_type + 1) << 8) | report_id, interface->desc.bInterfaceNumber, buf, count, USB_CTRL_SET_TIMEOUT); /* count also the report id, if this was a numbered report. */ @@ -1445,6 +1446,11 @@ static const struct hid_device_id hid_usb_table[] = { { } }; +struct usb_interface *usbhid_find_interface(int minor) +{ + return usb_find_interface(&hid_driver, minor); +} + static struct hid_driver hid_usb_driver = { .name = "generic-usb", .id_table = hid_usb_table, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2643d31..70da318 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -33,6 +33,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, @@ -69,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, @@ -77,6 +79,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, + { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, + { 0, 0 } }; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 0a29c51..681e620 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -270,7 +270,7 @@ static int hiddev_open(struct inode *inode, struct file *file) struct hiddev *hiddev; int res; - intf = usb_find_interface(&hiddev_driver, iminor(inode)); + intf = usbhid_find_interface(iminor(inode)); if (!intf) return -ENODEV; hid = usb_get_intfdata(intf); diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 693fd3e..89d2e84 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -42,6 +42,7 @@ void usbhid_submit_report (struct hid_device *hid, struct hid_report *report, unsigned char dir); int usbhid_get_power(struct hid_device *hid); void usbhid_put_power(struct hid_device *hid); +struct usb_interface *usbhid_find_interface(int minor); /* iofl flags */ #define HID_CTRL_RUNNING 1 diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 4d4d09b..97499d0 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -409,7 +409,7 @@ config SENSORS_CORETEMP config SENSORS_PKGTEMP tristate "Intel processor package temperature sensor" - depends on X86 && PCI && EXPERIMENTAL + depends on X86 && EXPERIMENTAL help If you say yes here you get support for the package level temperature sensor inside your CPU. Check documentation/driver for details. diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 15c1a96..0683e6b 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -79,7 +79,7 @@ struct adm1031_data { int chip_type; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - unsigned int update_rate; /* In milliseconds */ + unsigned int update_interval; /* In milliseconds */ /* The chan_select_table contains the possible configurations for * auto fan control. */ @@ -743,23 +743,23 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); -/* Update Rate */ -static const unsigned int update_rates[] = { +/* Update Interval */ +static const unsigned int update_intervals[] = { 16000, 8000, 4000, 2000, 1000, 500, 250, 125, }; -static ssize_t show_update_rate(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_update_interval(struct device *dev, + struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%u\n", data->update_rate); + return sprintf(buf, "%u\n", data->update_interval); } -static ssize_t set_update_rate(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t set_update_interval(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); @@ -771,12 +771,15 @@ static ssize_t set_update_rate(struct device *dev, if (err) return err; - /* find the nearest update rate from the table */ - for (i = 0; i < ARRAY_SIZE(update_rates) - 1; i++) { - if (val >= update_rates[i]) + /* + * Find the nearest update interval from the table. + * Use it to determine the matching update rate. + */ + for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) { + if (val >= update_intervals[i]) break; } - /* if not found, we point to the last entry (lowest update rate) */ + /* if not found, we point to the last entry (lowest update interval) */ /* set the new update rate while preserving other settings */ reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); @@ -785,14 +788,14 @@ static ssize_t set_update_rate(struct device *dev, adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); mutex_lock(&data->update_lock); - data->update_rate = update_rates[i]; + data->update_interval = update_intervals[i]; mutex_unlock(&data->update_lock); return count; } -static DEVICE_ATTR(update_rate, S_IRUGO | S_IWUSR, show_update_rate, - set_update_rate); +static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, + set_update_interval); static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, @@ -830,7 +833,7 @@ static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, - &dev_attr_update_rate.attr, + &dev_attr_update_interval.attr, &dev_attr_alarms.attr, NULL @@ -981,7 +984,8 @@ static void adm1031_init_client(struct i2c_client *client) mask = ADM1031_UPDATE_RATE_MASK; read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; - data->update_rate = update_rates[i]; + /* Save it as update interval */ + data->update_interval = update_intervals[i]; } static struct adm1031_data *adm1031_update_device(struct device *dev) @@ -993,7 +997,8 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) mutex_lock(&data->update_lock); - next_update = data->last_updated + msecs_to_jiffies(data->update_rate); + next_update = data->last_updated + + msecs_to_jiffies(data->update_interval); if (time_after(jiffies, next_update) || !data->valid) { dev_dbg(&client->dev, "Starting adm1031 update\n"); diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index de81111..a23b17a 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -36,6 +36,7 @@ #include <linux/pci.h> #include <asm/msr.h> #include <asm/processor.h> +#include <asm/smp.h> #define DRVNAME "coretemp" @@ -423,9 +424,18 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) int err; struct platform_device *pdev; struct pdev_entry *pdev_entry; -#ifdef CONFIG_SMP struct cpuinfo_x86 *c = &cpu_data(cpu); -#endif + + /* + * CPUID.06H.EAX[0] indicates whether the CPU has thermal + * sensors. We check this bit only, all the early CPUs + * without thermal sensors will be filtered out. + */ + if (!cpu_has(c, X86_FEATURE_DTS)) { + printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" + " has no thermal sensor.\n", c->x86_model); + return 0; + } mutex_lock(&pdev_list_mutex); @@ -482,14 +492,22 @@ exit: static void coretemp_device_remove(unsigned int cpu) { - struct pdev_entry *p, *n; + struct pdev_entry *p; + unsigned int i; + mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { - if (p->cpu == cpu) { - platform_device_unregister(p->pdev); - list_del(&p->list); - kfree(p); - } + list_for_each_entry(p, &pdev_list, list) { + if (p->cpu != cpu) + continue; + + platform_device_unregister(p->pdev); + list_del(&p->list); + mutex_unlock(&pdev_list_mutex); + kfree(p); + for_each_cpu(i, cpu_sibling_mask(cpu)) + if (i != cpu && !coretemp_device_add(i)) + break; + return; } mutex_unlock(&pdev_list_mutex); } @@ -527,30 +545,21 @@ static int __init coretemp_init(void) if (err) goto exit; - for_each_online_cpu(i) { - struct cpuinfo_x86 *c = &cpu_data(i); - /* - * CPUID.06H.EAX[0] indicates whether the CPU has thermal - * sensors. We check this bit only, all the early CPUs - * without thermal sensors will be filtered out. - */ - if (c->cpuid_level >= 6 && (cpuid_eax(0x06) & 0x01)) - coretemp_device_add(i); - else { - printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" - " has no thermal sensor.\n", c->x86_model); - } - } + for_each_online_cpu(i) + coretemp_device_add(i); + +#ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { err = -ENODEV; goto exit_driver_unreg; } +#endif register_hotcpu_notifier(&coretemp_cpu_notifier); return 0; -exit_driver_unreg: #ifndef CONFIG_HOTPLUG_CPU +exit_driver_unreg: platform_driver_unregister(&coretemp_driver); #endif exit: diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 5b58b20..8dee3f3 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -308,7 +308,6 @@ static int emc1403_probe(struct i2c_client *client, res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr); if (res) { dev_warn(&client->dev, "create group failed\n"); - hwmon_device_unregister(data->hwmon_dev); goto thermal_error1; } data->hwmon_dev = hwmon_device_register(&client->dev); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 537841e..75afb3b 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -111,7 +111,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -861,11 +861,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -877,6 +886,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2175,21 +2185,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2213,6 +2217,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2223,12 +2228,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2239,7 +2246,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 0f58ecc..9638d58 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -79,7 +79,7 @@ enum chips { f75373, f75375 }; #define F75375_REG_PWM2_DROP_DUTY 0x6C #define FAN_CTRL_LINEAR(nr) (4 + nr) -#define FAN_CTRL_MODE(nr) (5 + ((nr) * 2)) +#define FAN_CTRL_MODE(nr) (4 + ((nr) * 2)) /* * Data structures and manipulation thereof @@ -298,7 +298,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) return -EINVAL; fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); - fanmode = ~(3 << FAN_CTRL_MODE(nr)); + fanmode &= ~(3 << FAN_CTRL_MODE(nr)); switch (val) { case 0: /* Full speed */ @@ -350,7 +350,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); conf = f75375_read8(client, F75375_REG_CONFIG1); - conf = ~(1 << FAN_CTRL_LINEAR(nr)); + conf &= ~(1 << FAN_CTRL_LINEAR(nr)); if (val == 0) conf |= (1 << FAN_CTRL_LINEAR(nr)) ; diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 6138f03..fc591ae 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -277,7 +277,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy) wake_up_interruptible(&lis3_dev.misc_wait); kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN); out: - if (lis3_dev.whoami == WAI_8B && lis3_dev.idev && + if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev && lis3_dev.idev->input->users) return IRQ_WAKE_THREAD; return IRQ_HANDLED; @@ -718,7 +718,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) * io-apic is not configurable (and generates a warning) but I keep it * in case of support for other hardware. */ - if (dev->whoami == WAI_8B) + if (dev->pdata && dev->whoami == WAI_8B) thread_fn = lis302dl_interrupt_thread1_8b; else thread_fn = NULL; diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c index dc1f540..8e5933b 100644 --- a/drivers/hwmon/lis3lv02d_i2c.c +++ b/drivers/hwmon/lis3lv02d_i2c.c @@ -121,7 +121,7 @@ static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg) { struct lis3lv02d *lis3 = i2c_get_clientdata(client); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweroff(lis3); return 0; } @@ -130,7 +130,7 @@ static int lis3lv02d_i2c_resume(struct i2c_client *client) { struct lis3lv02d *lis3 = i2c_get_clientdata(client); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweron(lis3); return 0; } diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c index 82b1680..b9be5e3 100644 --- a/drivers/hwmon/lis3lv02d_spi.c +++ b/drivers/hwmon/lis3lv02d_spi.c @@ -92,7 +92,7 @@ static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg) { struct lis3lv02d *lis3 = spi_get_drvdata(spi); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweroff(&lis3_dev); return 0; @@ -102,7 +102,7 @@ static int lis3lv02d_spi_resume(struct spi_device *spi) { struct lis3lv02d *lis3 = spi_get_drvdata(spi); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweron(lis3); return 0; diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 94741d4..464340f 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -91,7 +91,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev); struct lm95241_data { struct device *hwmon_dev; struct mutex update_lock; - unsigned long last_updated, rate; /* in jiffies */ + unsigned long last_updated, interval; /* in jiffies */ char valid; /* zero until following fields are valid */ /* registers values */ u8 local_h, local_l; /* local */ @@ -114,23 +114,23 @@ show_temp(local); show_temp(remote1); show_temp(remote2); -static ssize_t show_rate(struct device *dev, struct device_attribute *attr, +static ssize_t show_interval(struct device *dev, struct device_attribute *attr, char *buf) { struct lm95241_data *data = lm95241_update_device(dev); - snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ); + snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ); return strlen(buf); } -static ssize_t set_rate(struct device *dev, struct device_attribute *attr, +static ssize_t set_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct lm95241_data *data = i2c_get_clientdata(client); - strict_strtol(buf, 10, &data->rate); - data->rate = data->rate * HZ / 1000; + strict_strtol(buf, 10, &data->interval); + data->interval = data->interval * HZ / 1000; return count; } @@ -286,7 +286,8 @@ static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); -static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate); +static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, + set_interval); static struct attribute *lm95241_attributes[] = { &dev_attr_temp1_input.attr, @@ -298,7 +299,7 @@ static struct attribute *lm95241_attributes[] = { &dev_attr_temp3_min.attr, &dev_attr_temp2_max.attr, &dev_attr_temp3_max.attr, - &dev_attr_rate.attr, + &dev_attr_update_interval.attr, NULL }; @@ -376,7 +377,7 @@ static void lm95241_init_client(struct i2c_client *client) { struct lm95241_data *data = i2c_get_clientdata(client); - data->rate = HZ; /* 1 sec default */ + data->interval = HZ; /* 1 sec default */ data->valid = 0; data->config = CFG_CR0076; data->model = 0; @@ -410,7 +411,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev) mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + data->rate) || + if (time_after(jiffies, data->last_updated + data->interval) || !data->valid) { dev_dbg(&client->dev, "Updating lm95241 data.\n"); data->local_h = diff --git a/drivers/hwmon/pkgtemp.c b/drivers/hwmon/pkgtemp.c index 74157fc..f119039 100644 --- a/drivers/hwmon/pkgtemp.c +++ b/drivers/hwmon/pkgtemp.c @@ -33,7 +33,6 @@ #include <linux/list.h> #include <linux/platform_device.h> #include <linux/cpu.h> -#include <linux/pci.h> #include <asm/msr.h> #include <asm/processor.h> @@ -224,7 +223,7 @@ static int __devinit pkgtemp_probe(struct platform_device *pdev) err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group); if (err) - goto exit_free; + goto exit_dev; data->hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->hwmon_dev)) { @@ -238,6 +237,8 @@ static int __devinit pkgtemp_probe(struct platform_device *pdev) exit_class: sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group); +exit_dev: + device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); exit_free: kfree(data); exit: @@ -250,6 +251,7 @@ static int __devexit pkgtemp_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group); + device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); platform_set_drvdata(pdev, NULL); kfree(data); return 0; @@ -281,9 +283,10 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu) int err; struct platform_device *pdev; struct pdev_entry *pdev_entry; -#ifdef CONFIG_SMP struct cpuinfo_x86 *c = &cpu_data(cpu); -#endif + + if (!cpu_has(c, X86_FEATURE_PTS)) + return 0; mutex_lock(&pdev_list_mutex); @@ -339,17 +342,18 @@ exit: #ifdef CONFIG_HOTPLUG_CPU static void pkgtemp_device_remove(unsigned int cpu) { - struct pdev_entry *p, *n; + struct pdev_entry *p; unsigned int i; int err; mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { + list_for_each_entry(p, &pdev_list, list) { if (p->cpu != cpu) continue; platform_device_unregister(p->pdev); list_del(&p->list); + mutex_unlock(&pdev_list_mutex); kfree(p); for_each_cpu(i, cpu_core_mask(cpu)) { if (i != cpu) { @@ -358,7 +362,7 @@ static void pkgtemp_device_remove(unsigned int cpu) break; } } - break; + return; } mutex_unlock(&pdev_list_mutex); } @@ -399,11 +403,6 @@ static int __init pkgtemp_init(void) goto exit; for_each_online_cpu(i) { - struct cpuinfo_x86 *c = &cpu_data(i); - - if (!cpu_has(c, X86_FEATURE_PTS)) - continue; - err = pkgtemp_device_add(i); if (err) goto exit_devices_unreg; diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index e96e69d..072c580 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -127,6 +127,7 @@ superio_enter(int ioreg) static inline void superio_exit(int ioreg) { + outb(0xaa, ioreg); outb(0x02, ioreg); outb(0x02, ioreg + 1); } diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index f7bd261..f2de3be 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -677,6 +677,11 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev, dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", cpm->adap.name); + /* + * register OF I2C devices + */ + of_i2c_register_devices(&cpm->adap); + return 0; out_shut: cpm_i2c_shutdown(cpm); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 2222c87..b8feac5 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -357,9 +357,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; - /* write the data into mode register */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before @@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->buf_len--; } + /* write the data into mode register; start transmitting */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, dev->adapter.timeout); if (r == 0) { diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 43ca32f..89eedf4 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -761,6 +761,9 @@ static int __devinit iic_probe(struct platform_device *ofdev, dev_info(&ofdev->dev, "using %s mode\n", dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); + /* Now register all the child nodes */ + of_i2c_register_devices(adap); + return 0; error_cleanup: diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index a1c419a..b74e6dc 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -632,6 +632,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op, dev_err(i2c->dev, "failed to add adapter\n"); goto fail_add; } + of_i2c_register_devices(&i2c->adap); return result; diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 0e9f85d..56dbe54 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -218,7 +218,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) return result; } else if (result == 0) { dev_dbg(i2c->dev, "%s: timeout\n", __func__); - result = -ETIMEDOUT; + return -ETIMEDOUT; } return 0; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 7674efb..b33c785 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -680,6 +680,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r == 0) r = num; + + omap_i2c_wait_for_bb(dev); out: omap_i2c_idle(dev); return r; diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index bbd7760..29933f8 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -71,8 +71,8 @@ static int pca_isa_readbyte(void *pd, int reg) static int pca_isa_waitforcompletion(void *pd) { - long ret = ~0; unsigned long timeout; + long ret; if (irq > -1) { ret = wait_event_timeout(pca_wait, @@ -81,11 +81,15 @@ static int pca_isa_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + pca_isa_ops.timeout; - while (((pca_isa_readbyte(pd, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } + return ret > 0; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index ef5c784..5f6d7f8 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -80,8 +80,8 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) static int i2c_pca_pf_waitforcompletion(void *pd) { struct i2c_pca_pf_data *i2c = pd; - long ret = ~0; unsigned long timeout; + long ret; if (i2c->irq) { ret = wait_event_timeout(i2c->wait, @@ -90,10 +90,13 @@ static int i2c_pca_pf_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + i2c->adap.timeout; - while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } return ret > 0; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 72902e0..bf831bf 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -662,8 +662,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) unsigned long sda_delay; if (pdata->sda_delay) { - sda_delay = (freq / 1000) * pdata->sda_delay; - sda_delay /= 1000000; + sda_delay = clkin * pdata->sda_delay; + sda_delay = DIV_ROUND_UP(sda_delay, 1000000); sda_delay = DIV_ROUND_UP(sda_delay, 5); if (sda_delay > 3) sda_delay = 3; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 6649176..bea4c50 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -32,7 +32,6 @@ #include <linux/init.h> #include <linux/idr.h> #include <linux/mutex.h> -#include <linux/of_i2c.h> #include <linux/of_device.h> #include <linux/completion.h> #include <linux/hardirq.h> @@ -197,11 +196,12 @@ static int i2c_device_pm_suspend(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->suspend ? pm->suspend(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->suspend ? pm->suspend(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_SUSPEND); } @@ -216,12 +216,6 @@ static int i2c_device_pm_resume(struct device *dev) else ret = i2c_legacy_resume(dev); - if (!ret) { - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } - return ret; } @@ -229,11 +223,12 @@ static int i2c_device_pm_freeze(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->freeze ? pm->freeze(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->freeze ? pm->freeze(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_FREEZE); } @@ -242,11 +237,12 @@ static int i2c_device_pm_thaw(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->thaw ? pm->thaw(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->thaw ? pm->thaw(dev) : 0; + } return i2c_legacy_resume(dev); } @@ -255,11 +251,12 @@ static int i2c_device_pm_poweroff(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->poweroff ? pm->poweroff(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->poweroff ? pm->poweroff(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_HIBERNATE); } @@ -876,9 +873,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); - /* Register devices from the device tree */ - of_i2c_register_devices(adap); - /* Notify drivers */ mutex_lock(&core_lock); bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 4c3d1bf..068cef0 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1448,19 +1448,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (hwif == NULL) continue; - if (hwif->present) - hwif_register_devices(hwif); - } - - ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) - continue; - ide_sysfs_register_port(hwif); ide_proc_register_port(hwif); - if (hwif->present) + if (hwif->present) { ide_proc_port_register_devices(hwif); + hwif_register_devices(hwif); + } } return j ? 0 : -1; diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index a10152b..c37ef64 100755..100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -83,7 +83,7 @@ static unsigned int mwait_substates; /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ static unsigned int lapic_timer_reliable_states; -static struct cpuidle_device *intel_idle_cpuidle_devices; +static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); static struct cpuidle_state *cpuidle_state_table; @@ -108,7 +108,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { .name = "NHM-C3", .desc = "MWAIT 0x10", .driver_data = (void *) 0x10, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 20, .power_usage = 500, .target_residency = 80, @@ -117,7 +117,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { .name = "NHM-C6", .desc = "MWAIT 0x20", .driver_data = (void *) 0x20, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 200, .power_usage = 350, .target_residency = 800, @@ -149,7 +149,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { .name = "ATM-C4", .desc = "MWAIT 0x30", .driver_data = (void *) 0x30, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 100, .power_usage = 250, .target_residency = 400, @@ -157,13 +157,13 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C5 */ }, { /* MWAIT C6 */ .name = "ATM-C6", - .desc = "MWAIT 0x40", - .driver_data = (void *) 0x40, - .flags = CPUIDLE_FLAG_TIME_VALID, - .exit_latency = 200, + .desc = "MWAIT 0x52", + .driver_data = (void *) 0x52, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 140, .power_usage = 150, - .target_residency = 800, - .enter = NULL }, /* disabled */ + .target_residency = 560, + .enter = &intel_idle }, }; /** @@ -185,6 +185,16 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) local_irq_disable(); + /* + * If the state flag indicates that the TLB will be flushed or if this + * is the deepest c-state supported, do a voluntary leave mm to avoid + * costly and mostly unnecessary wakeups for flushing the user TLB's + * associated with the active mm. + */ + if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED || + (&dev->states[dev->state_count - 1] == state)) + leave_mm(cpu); + if (!(lapic_timer_reliable_states & (1 << (cstate)))) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index d88077a..13c8887 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -463,7 +463,8 @@ static int send_connect(struct iwch_ep *ep) V_MSS_IDX(mtu_idx) | V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx); opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10); - opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor); + opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) | + V_CONG_CONTROL_FLAVOR(cong_flavor); skb->priority = CPL_PRIORITY_SETUP; set_arp_failure_handler(skb, act_open_req_arp_failure); @@ -1280,7 +1281,8 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb) V_MSS_IDX(mtu_idx) | V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx); opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10); - opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor); + opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) | + V_CONG_CONTROL_FLAVOR(cong_flavor); rpl = cplhdr(skb); rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index d85bd8a..22239e9 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -483,6 +483,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, memcpy(joydev->abspam, abspam, len); + for (i = 0; i < joydev->nabs; i++) + joydev->absmap[joydev->abspam[i]] = i; + out: kfree(abspam); return retval; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9cc488d..aa037fe 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -338,7 +338,7 @@ config KEYBOARD_OPENCORES config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" - depends on PXA27x || PXA3xx + depends on PXA27x || PXA3xx || ARCH_MMP help Enable support for PXA27x/PXA3xx keypad controller. diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index f32404f..4b0ec35 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -32,7 +32,7 @@ #include <asm/mach/map.h> #include <mach/hardware.h> -#include <mach/pxa27x_keypad.h> +#include <plat/pxa27x_keypad.h> /* * Keypad Controller registers */ @@ -330,11 +330,21 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) keypad->direct_key_state = new_state; } +static void clear_wakeup_event(struct pxa27x_keypad *keypad) +{ + struct pxa27x_keypad_platform_data *pdata = keypad->pdata; + + if (pdata->clear_wakeup_event) + (pdata->clear_wakeup_event)(); +} + static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) { struct pxa27x_keypad *keypad = dev_id; unsigned long kpc = keypad_readl(KPC); + clear_wakeup_event(keypad); + if (kpc & KPC_DI) pxa27x_keypad_scan_direct(keypad); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 0d4266a..3606985 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -404,6 +404,13 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu retval = uinput_validate_absbits(dev); if (retval < 0) goto exit; + if (test_bit(ABS_MT_SLOT, dev->absbit)) { + int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1; + input_mt_create_slots(dev, nslot); + input_set_events_per_packet(dev, 6 * nslot); + } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { + input_set_events_per_packet(dev, 60); + } } udev->state = UIST_SETUP_COMPLETE; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 42ba369..b35876e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -103,27 +103,26 @@ static void wacom_sys_irq(struct urb *urb) static int wacom_open(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); + int retval = 0; - mutex_lock(&wacom->lock); - - wacom->irq->dev = wacom->usbdev; - - if (usb_autopm_get_interface(wacom->intf) < 0) { - mutex_unlock(&wacom->lock); + if (usb_autopm_get_interface(wacom->intf) < 0) return -EIO; - } + + mutex_lock(&wacom->lock); if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { - usb_autopm_put_interface(wacom->intf); - mutex_unlock(&wacom->lock); - return -EIO; + retval = -EIO; + goto out; } wacom->open = true; wacom->intf->needs_remote_wakeup = 1; +out: mutex_unlock(&wacom->lock); - return 0; + if (retval) + usb_autopm_put_interface(wacom->intf); + return retval; } static void wacom_close(struct input_dev *dev) @@ -135,6 +134,8 @@ static void wacom_close(struct input_dev *dev) wacom->open = false; wacom->intf->needs_remote_wakeup = 0; mutex_unlock(&wacom->lock); + + usb_autopm_put_interface(wacom->intf); } static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 6e29bad..47fd7a0 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -442,8 +442,10 @@ static void wacom_intuos_general(struct wacom_wac *wacom) /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if (features->type >= INTUOS4S && features->type <= INTUOS4L) + if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || + features->type == WACOM_21UX2) { t = (t << 1) | (data[1] & 1); + } input_report_abs(input, ABS_PRESSURE, t); input_report_abs(input, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c index 485be8b..f0225bc 100644 --- a/drivers/isdn/sc/interrupt.c +++ b/drivers/isdn/sc/interrupt.c @@ -112,11 +112,19 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) } else if(callid>=0x0000 && callid<=0x7FFF) { + int len; + pr_debug("%s: Got Incoming Call\n", sc_adapter[card]->devicename); - strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4])); - strcpy(setup.eazmsn, - sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn); + len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]), + sizeof(setup.phone)); + if (len >= sizeof(setup.phone)) + continue; + len = strlcpy(setup.eazmsn, + sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, + sizeof(setup.eazmsn)); + if (len >= sizeof(setup.eazmsn)) + continue; setup.si1 = 7; setup.si2 = 0; setup.plan = 0; @@ -176,7 +184,9 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) * Handle a GetMyNumber Rsp */ if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){ - strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array); + strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, + rcvmsg.msg_data.byte_array, + sizeof(rcvmsg.msg_data.byte_array)); continue; } diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index e411262..cc2a88d 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -304,13 +304,22 @@ config LEDS_MC13783 config LEDS_NS2 tristate "LED support for Network Space v2 GPIO LEDs" - depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 + depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 || D2NET_V2 default y help This option enable support for the dual-GPIO LED found on the Network Space v2 board (and parents). This include Internet Space v2, Network Space (Max) v2 and d2 Network v2 boards. +config LEDS_NETXBIG + tristate "LED support for Big Network series LEDs" + depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2 + default y + help + This option enable support for LEDs found on the LaCie 2Big + and 5Big Network v2 boards. The LEDs are wired to a CPLD and are + controlled through a GPIO extension bus. + config LEDS_TRIGGERS bool "LED Trigger support" help diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 7d6b958..9c96db4 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o obj-$(CONFIG_LEDS_NS2) += leds-ns2.o +obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c new file mode 100644 index 0000000..f2e51c1 --- /dev/null +++ b/drivers/leds/leds-netxbig.c @@ -0,0 +1,449 @@ +/* + * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs + * + * Copyright (C) 2010 LaCie + * + * Author: Simon Guinot <sguinot@lacie.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/leds.h> +#include <mach/leds-netxbig.h> + +/* + * GPIO extension bus. + */ + +static DEFINE_SPINLOCK(gpio_ext_lock); + +static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr) +{ + int pin; + + for (pin = 0; pin < gpio_ext->num_addr; pin++) + gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1); +} + +static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data) +{ + int pin; + + for (pin = 0; pin < gpio_ext->num_data; pin++) + gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1); +} + +static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext) +{ + /* Enable select is done on the raising edge. */ + gpio_set_value(gpio_ext->enable, 0); + gpio_set_value(gpio_ext->enable, 1); +} + +static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext, + int addr, int value) +{ + unsigned long flags; + + spin_lock_irqsave(&gpio_ext_lock, flags); + gpio_ext_set_addr(gpio_ext, addr); + gpio_ext_set_data(gpio_ext, value); + gpio_ext_enable_select(gpio_ext); + spin_unlock_irqrestore(&gpio_ext_lock, flags); +} + +static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) +{ + int err; + int i; + + if (unlikely(!gpio_ext)) + return -EINVAL; + + /* Configure address GPIOs. */ + for (i = 0; i < gpio_ext->num_addr; i++) { + err = gpio_request(gpio_ext->addr[i], "GPIO extension addr"); + if (err) + goto err_free_addr; + err = gpio_direction_output(gpio_ext->addr[i], 0); + if (err) { + gpio_free(gpio_ext->addr[i]); + goto err_free_addr; + } + } + /* Configure data GPIOs. */ + for (i = 0; i < gpio_ext->num_data; i++) { + err = gpio_request(gpio_ext->data[i], "GPIO extension data"); + if (err) + goto err_free_data; + err = gpio_direction_output(gpio_ext->data[i], 0); + if (err) { + gpio_free(gpio_ext->data[i]); + goto err_free_data; + } + } + /* Configure "enable select" GPIO. */ + err = gpio_request(gpio_ext->enable, "GPIO extension enable"); + if (err) + goto err_free_data; + err = gpio_direction_output(gpio_ext->enable, 0); + if (err) { + gpio_free(gpio_ext->enable); + goto err_free_data; + } + + return 0; + +err_free_data: + for (i = i - 1; i >= 0; i--) + gpio_free(gpio_ext->data[i]); + i = gpio_ext->num_addr; +err_free_addr: + for (i = i - 1; i >= 0; i--) + gpio_free(gpio_ext->addr[i]); + + return err; +} + +static void __devexit gpio_ext_free(struct netxbig_gpio_ext *gpio_ext) +{ + int i; + + gpio_free(gpio_ext->enable); + for (i = gpio_ext->num_addr - 1; i >= 0; i--) + gpio_free(gpio_ext->addr[i]); + for (i = gpio_ext->num_data - 1; i >= 0; i--) + gpio_free(gpio_ext->data[i]); +} + +/* + * Class LED driver. + */ + +struct netxbig_led_data { + struct netxbig_gpio_ext *gpio_ext; + struct led_classdev cdev; + int mode_addr; + int *mode_val; + int bright_addr; + int bright_max; + struct netxbig_led_timer *timer; + int num_timer; + enum netxbig_led_mode mode; + int sata; + spinlock_t lock; +}; + +static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode, + unsigned long delay_on, + unsigned long delay_off, + struct netxbig_led_timer *timer, + int num_timer) +{ + int i; + + for (i = 0; i < num_timer; i++) { + if (timer[i].delay_on == delay_on && + timer[i].delay_off == delay_off) { + *mode = timer[i].mode; + return 0; + } + } + return -EINVAL; +} + +static int netxbig_led_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct netxbig_led_data *led_dat = + container_of(led_cdev, struct netxbig_led_data, cdev); + enum netxbig_led_mode mode; + int mode_val; + int ret; + + /* Look for a LED mode with the requested timer frequency. */ + ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off, + led_dat->timer, led_dat->num_timer); + if (ret < 0) + return ret; + + mode_val = led_dat->mode_val[mode]; + if (mode_val == NETXBIG_LED_INVALID_MODE) + return -EINVAL; + + spin_lock_irq(&led_dat->lock); + + gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); + led_dat->mode = mode; + + spin_unlock_irq(&led_dat->lock); + + return 0; +} + +static void netxbig_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct netxbig_led_data *led_dat = + container_of(led_cdev, struct netxbig_led_data, cdev); + enum netxbig_led_mode mode; + int mode_val, bright_val; + int set_brightness = 1; + unsigned long flags; + + spin_lock_irqsave(&led_dat->lock, flags); + + if (value == LED_OFF) { + mode = NETXBIG_LED_OFF; + set_brightness = 0; + } else { + if (led_dat->sata) + mode = NETXBIG_LED_SATA; + else if (led_dat->mode == NETXBIG_LED_OFF) + mode = NETXBIG_LED_ON; + else /* Keep 'timer' mode. */ + mode = led_dat->mode; + } + mode_val = led_dat->mode_val[mode]; + + gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); + led_dat->mode = mode; + /* + * Note that the brightness register is shared between all the + * SATA LEDs. So, change the brightness setting for a single + * SATA LED will affect all the others. + */ + if (set_brightness) { + bright_val = DIV_ROUND_UP(value * led_dat->bright_max, + LED_FULL); + gpio_ext_set_value(led_dat->gpio_ext, + led_dat->bright_addr, bright_val); + } + + spin_unlock_irqrestore(&led_dat->lock, flags); +} + +static ssize_t netxbig_led_sata_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct netxbig_led_data *led_dat = + container_of(led_cdev, struct netxbig_led_data, cdev); + unsigned long enable; + enum netxbig_led_mode mode; + int mode_val; + int ret; + + ret = strict_strtoul(buff, 10, &enable); + if (ret < 0) + return ret; + + enable = !!enable; + + spin_lock_irq(&led_dat->lock); + + if (led_dat->sata == enable) { + ret = count; + goto exit_unlock; + } + + if (led_dat->mode != NETXBIG_LED_ON && + led_dat->mode != NETXBIG_LED_SATA) + mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */ + else if (enable) + mode = NETXBIG_LED_SATA; + else + mode = NETXBIG_LED_ON; + + mode_val = led_dat->mode_val[mode]; + if (mode_val == NETXBIG_LED_INVALID_MODE) { + ret = -EINVAL; + goto exit_unlock; + } + + gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); + led_dat->mode = mode; + led_dat->sata = enable; + + ret = count; + +exit_unlock: + spin_unlock_irq(&led_dat->lock); + + return ret; +} + +static ssize_t netxbig_led_sata_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct netxbig_led_data *led_dat = + container_of(led_cdev, struct netxbig_led_data, cdev); + + return sprintf(buf, "%d\n", led_dat->sata); +} + +static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); + +static void __devexit delete_netxbig_led(struct netxbig_led_data *led_dat) +{ + if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) + device_remove_file(led_dat->cdev.dev, &dev_attr_sata); + led_classdev_unregister(&led_dat->cdev); +} + +static int __devinit +create_netxbig_led(struct platform_device *pdev, + struct netxbig_led_data *led_dat, + const struct netxbig_led *template) +{ + struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; + int ret; + + spin_lock_init(&led_dat->lock); + led_dat->gpio_ext = pdata->gpio_ext; + led_dat->cdev.name = template->name; + led_dat->cdev.default_trigger = template->default_trigger; + led_dat->cdev.blink_set = netxbig_led_blink_set; + led_dat->cdev.brightness_set = netxbig_led_set; + /* + * Because the GPIO extension bus don't allow to read registers + * value, there is no way to probe the LED initial state. + * So, the initial sysfs LED value for the "brightness" and "sata" + * attributes are inconsistent. + * + * Note that the initial LED state can't be reconfigured. + * The reason is that the LED behaviour must stay uniform during + * the whole boot process (bootloader+linux). + */ + led_dat->sata = 0; + led_dat->cdev.brightness = LED_OFF; + led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; + led_dat->mode_addr = template->mode_addr; + led_dat->mode_val = template->mode_val; + led_dat->bright_addr = template->bright_addr; + led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1; + led_dat->timer = pdata->timer; + led_dat->num_timer = pdata->num_timer; + + ret = led_classdev_register(&pdev->dev, &led_dat->cdev); + if (ret < 0) + return ret; + + /* + * If available, expose the SATA activity blink capability through + * a "sata" sysfs attribute. + */ + if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) { + ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); + if (ret) + led_classdev_unregister(&led_dat->cdev); + } + + return ret; +} + +static int __devinit netxbig_led_probe(struct platform_device *pdev) +{ + struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; + struct netxbig_led_data *leds_data; + int i; + int ret; + + if (!pdata) + return -EINVAL; + + leds_data = kzalloc(sizeof(struct netxbig_led_data) * pdata->num_leds, + GFP_KERNEL); + if (!leds_data) + return -ENOMEM; + + ret = gpio_ext_init(pdata->gpio_ext); + if (ret < 0) + goto err_free_data; + + for (i = 0; i < pdata->num_leds; i++) { + ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]); + if (ret < 0) + goto err_free_leds; + } + + platform_set_drvdata(pdev, leds_data); + + return 0; + +err_free_leds: + for (i = i - 1; i >= 0; i--) + delete_netxbig_led(&leds_data[i]); + + gpio_ext_free(pdata->gpio_ext); +err_free_data: + kfree(leds_data); + + return ret; +} + +static int __devexit netxbig_led_remove(struct platform_device *pdev) +{ + struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; + struct netxbig_led_data *leds_data; + int i; + + leds_data = platform_get_drvdata(pdev); + + for (i = 0; i < pdata->num_leds; i++) + delete_netxbig_led(&leds_data[i]); + + gpio_ext_free(pdata->gpio_ext); + kfree(leds_data); + + return 0; +} + +static struct platform_driver netxbig_led_driver = { + .probe = netxbig_led_probe, + .remove = __devexit_p(netxbig_led_remove), + .driver = { + .name = "leds-netxbig", + .owner = THIS_MODULE, + }, +}; +MODULE_ALIAS("platform:leds-netxbig"); + +static int __init netxbig_led_init(void) +{ + return platform_driver_register(&netxbig_led_driver); +} + +static void __exit netxbig_led_exit(void) +{ + platform_driver_unregister(&netxbig_led_driver); +} + +module_init(netxbig_led_init); +module_exit(netxbig_led_exit); + +MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); +MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 74dce4b..f77d48d 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -81,7 +81,7 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat, int cmd_level; int slow_level; - read_lock(&led_dat->rw_lock); + read_lock_irq(&led_dat->rw_lock); cmd_level = gpio_get_value(led_dat->cmd); slow_level = gpio_get_value(led_dat->slow); @@ -95,7 +95,7 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat, } } - read_unlock(&led_dat->rw_lock); + read_unlock_irq(&led_dat->rw_lock); return ret; } @@ -104,8 +104,9 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat, enum ns2_led_modes mode) { int i; + unsigned long flags; - write_lock(&led_dat->rw_lock); + write_lock_irqsave(&led_dat->rw_lock, flags); for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) { if (mode == ns2_led_modval[i].mode) { @@ -116,7 +117,7 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat, } } - write_unlock(&led_dat->rw_lock); + write_unlock_irqrestore(&led_dat->rw_lock, flags); } static void ns2_led_set(struct led_classdev *led_cdev, @@ -140,10 +141,12 @@ static ssize_t ns2_led_sata_store(struct device *dev, struct device_attribute *attr, const char *buff, size_t count) { + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct ns2_led_data *led_dat = + container_of(led_cdev, struct ns2_led_data, cdev); int ret; unsigned long enable; enum ns2_led_modes mode; - struct ns2_led_data *led_dat = dev_get_drvdata(dev); ret = strict_strtoul(buff, 10, &enable); if (ret < 0) @@ -171,7 +174,9 @@ static ssize_t ns2_led_sata_store(struct device *dev, static ssize_t ns2_led_sata_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct ns2_led_data *led_dat = dev_get_drvdata(dev); + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct ns2_led_data *led_dat = + container_of(led_cdev, struct ns2_led_data, cdev); return sprintf(buf, "%d\n", led_dat->sata); } @@ -233,7 +238,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, if (ret < 0) goto err_free_slow; - dev_set_drvdata(led_dat->cdev.dev, led_dat); ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); if (ret < 0) goto err_free_cdev; diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index ed4900a..e4fb58d 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1000,10 +1000,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) page = bitmap->sb_page; offset = sizeof(bitmap_super_t); if (!file) - read_sb_page(bitmap->mddev, - bitmap->mddev->bitmap_info.offset, - page, - index, count); + page = read_sb_page( + bitmap->mddev, + bitmap->mddev->bitmap_info.offset, + page, + index, count); } else if (file) { page = read_page(file, index, bitmap, count); offset = 0; diff --git a/drivers/md/md.c b/drivers/md/md.c index 43cf9cc..f20d13e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1643,7 +1643,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; if (rdev->sb_size & bmask) rdev->sb_size = (rdev->sb_size | bmask) + 1; - } + } else + max_dev = le32_to_cpu(sb->max_dev); + for (i=0; i<max_dev;i++) sb->dev_roles[i] = cpu_to_le16(0xfffe); @@ -7069,7 +7071,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) return; if ( ! ( - (mddev->flags && !mddev->external) || + (mddev->flags & ~ (1<<MD_CHANGE_PENDING)) || test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || test_bit(MD_RECOVERY_DONE, &mddev->recovery) || (mddev->external == 0 && mddev->safemode == 1) || diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index ad83a4d..0b830bb 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1839,7 +1839,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i /* take from bio_init */ bio->bi_next = NULL; + bio->bi_flags &= ~(BIO_POOL_MASK-1); bio->bi_flags |= 1 << BIO_UPTODATE; + bio->bi_comp_cpu = -1; bio->bi_rw = READ; bio->bi_vcnt = 0; bio->bi_idx = 0; @@ -1912,7 +1914,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) break; BUG_ON(sync_blocks < (PAGE_SIZE>>9)); - if (len > (sync_blocks<<9)) + if ((len >> 9) > sync_blocks) len = sync_blocks<<9; } diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 7e82a9d..7961d59 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -319,7 +319,7 @@ static void ir_timer_keyup(unsigned long cookie) * a keyup event might follow immediately after the keydown. */ spin_lock_irqsave(&ir->keylock, flags); - if (time_is_after_eq_jiffies(ir->keyup_jiffies)) + if (time_is_before_eq_jiffies(ir->keyup_jiffies)) ir_keyup(ir); spin_unlock_irqrestore(&ir->keylock, flags); } @@ -510,6 +510,13 @@ int __ir_input_register(struct input_dev *input_dev, (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? " in raw mode" : ""); + /* + * Default delay of 250ms is too short for some protocols, expecially + * since the timeout is currently set to 250ms. Increase it to 500ms, + * to avoid wrong repetition of the keycodes. + */ + input_dev->rep[REP_DELAY] = 500; + return 0; out_event: diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 77b5946..e63f757 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c @@ -267,7 +267,7 @@ static int ir_lirc_register(struct input_dev *input_dev) features |= LIRC_CAN_SET_SEND_CARRIER; if (ir_dev->props->s_tx_duty_cycle) - features |= LIRC_CAN_SET_REC_DUTY_CYCLE; + features |= LIRC_CAN_SET_SEND_DUTY_CYCLE; } if (ir_dev->props->s_rx_carrier_range) diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 43094e7..8e0e1b1 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -279,9 +279,11 @@ int ir_raw_event_register(struct input_dev *input_dev) "rc%u", (unsigned int)ir->devno); if (IS_ERR(ir->raw->thread)) { + int ret = PTR_ERR(ir->raw->thread); + kfree(ir->raw); ir->raw = NULL; - return PTR_ERR(ir->raw->thread); + return ret; } mutex_lock(&ir_raw_handler_lock); diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 96dafc4..46d4246 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -67,13 +67,14 @@ static ssize_t show_protocols(struct device *d, char *tmp = buf; int i; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { enabled = ir_dev->rc_tab.ir_type; allowed = ir_dev->props->allowed_protos; - } else { + } else if (ir_dev->raw) { enabled = ir_dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } + } else + return sprintf(tmp, "[builtin]\n"); IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, @@ -121,10 +122,14 @@ static ssize_t store_protocols(struct device *d, int rc, i, count = 0; unsigned long flags; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) type = ir_dev->rc_tab.ir_type; - else + else if (ir_dev->raw) type = ir_dev->raw->enabled_protocols; + else { + IR_dprintk(1, "Protocol switching not supported\n"); + return -EINVAL; + } while ((tmp = strsep((char **) &data, " \n")) != NULL) { if (!*tmp) @@ -185,7 +190,7 @@ static ssize_t store_protocols(struct device *d, } } - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); ir_dev->rc_tab.ir_type = type; spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c index 64264f7..39557ad 100644 --- a/drivers/media/IR/keymaps/rc-rc6-mce.c +++ b/drivers/media/IR/keymaps/rc-rc6-mce.c @@ -19,6 +19,7 @@ static struct ir_scancode rc6_mce[] = { { 0x800f0416, KEY_PLAY }, { 0x800f0418, KEY_PAUSE }, + { 0x800f046e, KEY_PLAYPAUSE }, { 0x800f0419, KEY_STOP }, { 0x800f0417, KEY_RECORD }, @@ -37,6 +38,8 @@ static struct ir_scancode rc6_mce[] = { { 0x800f0411, KEY_VOLUMEDOWN }, { 0x800f0412, KEY_CHANNELUP }, { 0x800f0413, KEY_CHANNELDOWN }, + { 0x800f043a, KEY_BRIGHTNESSUP }, + { 0x800f0480, KEY_BRIGHTNESSDOWN }, { 0x800f0401, KEY_NUMERIC_1 }, { 0x800f0402, KEY_NUMERIC_2 }, diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c index ac6bb2c..bc620e1 100644 --- a/drivers/media/IR/mceusb.c +++ b/drivers/media/IR/mceusb.c @@ -120,6 +120,10 @@ static struct usb_device_id mceusb_dev_table[] = { { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, /* Philips eHome Infrared Transceiver */ { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, + /* Philips/Spinel plus IR transceiver for ASUS */ + { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, + /* Philips/Spinel plus IR transceiver for ASUS */ + { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, /* Realtek MCE IR Receiver */ { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, /* SMK/Toshiba G83C0004D410 */ diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index fe81834..48397f1 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -673,9 +673,6 @@ static int dib0700_probe(struct usb_interface *intf, else dev->props.rc.core.bulk_mode = false; - /* Need a higher delay, to avoid wrong repeat */ - dev->rc_input_dev->rep[REP_DELAY] = 500; - dib0700_rc_setup(dev); return 0; diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index f634d2e..e06acd1 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -940,6 +940,58 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe == NULL ? -ENODEV : 0; } +/* STK7770P */ +static struct dib7000p_config dib7770p_dib7000p_config = { + .output_mpeg2_in_188_bytes = 1, + + .agc_config_count = 1, + .agc = &dib7070_agc_config, + .bw = &dib7070_bw_config_12_mhz, + .tuner_is_baseband = 1, + .spur_protect = 1, + + .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, + + .hostbus_diversity = 1, + .enable_current_mirror = 1, + .disable_sample_and_hold = 0, +}; + +static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct usb_device_descriptor *p = &adap->dev->udev->descriptor; + if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && + p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + else + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + + dib0700_ctrl_clock(adap->dev, 72, 1); + + msleep(10); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, + &dib7770p_dib7000p_config) != 0) { + err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", + __func__); + return -ENODEV; + } + + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, + &dib7770p_dib7000p_config); + return adap->fe == NULL ? -ENODEV : 0; +} + /* DIB807x generic */ static struct dibx000_agc_config dib807x_agc_config[2] = { { @@ -1781,7 +1833,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, - { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, + { USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) }, { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, @@ -2406,7 +2458,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { .pid_filter_count = 32, .pid_filter = stk70x0p_pid_filter, .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, - .frontend_attach = stk7070p_frontend_attach, + .frontend_attach = stk7770p_frontend_attach, .tuner_attach = dib7770p_tuner_attach, DIB0700_DEFAULT_STREAMING_CONFIG(0x02), diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 6b22ec6..f896337 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -483,9 +483,7 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev, } } kfree(p); - if (fw) { - release_firmware(fw); - } + release_firmware(fw); return ret; } diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 2e28b97..3aed0d4 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -260,6 +260,9 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad // dprintk( "908: %x, 909: %x\n", reg_908, reg_909); + reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4; + reg_908 |= (state->cfg.enable_current_mirror & 1) << 7; + dib7000p_write_word(state, 908, reg_908); dib7000p_write_word(state, 909, reg_909); } @@ -778,7 +781,10 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte default: case GUARD_INTERVAL_1_32: value *= 1; break; } - state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO + if (state->cfg.diversity_delay == 0) + state->div_sync_wait = (value * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo + else + state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for one DVSY-fifo /* deactive the possibility of diversity reception if extended interleaver */ state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K; diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 805dd13..da17345 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -33,6 +33,11 @@ struct dib7000p_config { int (*agc_control) (struct dvb_frontend *, u8 before); u8 output_mode; + u8 disable_sample_and_hold : 1; + + u8 enable_current_mirror : 1; + u8 diversity_delay; + }; #define DEFAULT_DIB7000P_I2C_ADDRESS 18 diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index d93468c..ff3b0fa 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -1098,33 +1098,26 @@ EXPORT_SYMBOL_GPL(smscore_onresponse); * * @return pointer to descriptor on success, NULL on error. */ -struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) + +struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev) { struct smscore_buffer_t *cb = NULL; unsigned long flags; - DEFINE_WAIT(wait); - spin_lock_irqsave(&coredev->bufferslock, flags); - - /* This function must return a valid buffer, since the buffer list is - * finite, we check that there is an available buffer, if not, we wait - * until such buffer become available. - */ - - prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); - if (list_empty(&coredev->buffers)) { - spin_unlock_irqrestore(&coredev->bufferslock, flags); - schedule(); - spin_lock_irqsave(&coredev->bufferslock, flags); + if (!list_empty(&coredev->buffers)) { + cb = (struct smscore_buffer_t *) coredev->buffers.next; + list_del(&cb->entry); } + spin_unlock_irqrestore(&coredev->bufferslock, flags); + return cb; +} - finish_wait(&coredev->buffer_mng_waitq, &wait); - - cb = (struct smscore_buffer_t *) coredev->buffers.next; - list_del(&cb->entry); +struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) +{ + struct smscore_buffer_t *cb = NULL; - spin_unlock_irqrestore(&coredev->bufferslock, flags); + wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev))); return cb; } diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 67a4ec8..4ce541a 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -395,7 +395,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, radio->registers[POWERCFG] = POWERCFG_ENABLE; if (si470x_set_register(radio, POWERCFG) < 0) { retval = -EIO; - goto err_all; + goto err_video; } msleep(110); diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile index 755dd0c..6f2b573 100644 --- a/drivers/media/video/cx231xx/Makefile +++ b/drivers/media/video/cx231xx/Makefile @@ -11,4 +11,5 @@ EXTRA_CFLAGS += -Idrivers/media/video EXTRA_CFLAGS += -Idrivers/media/common/tuners EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 6bdc0ef..f2a4900 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -32,6 +32,7 @@ #include <media/v4l2-chip-ident.h> #include <media/cx25840.h> +#include "dvb-usb-ids.h" #include "xc5000.h" #include "cx231xx.h" @@ -175,6 +176,8 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_CNXT_RDE_250}, {USB_DEVICE(0x0572, 0x58A1), .driver_info = CX231XX_BOARD_CNXT_RDU_250}, + {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff), + .driver_info = CX231XX_BOARD_UNKNOWN}, {}, }; @@ -226,14 +229,16 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) dev->board.name, dev->model); /* set the direction for GPIO pins */ - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); + if (dev->board.tuner_gpio) { + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); - /* request some modules if any required */ + /* request some modules if any required */ - /* reset the Tuner */ - cx231xx_gpio_set(dev, dev->board.tuner_gpio); + /* reset the Tuner */ + cx231xx_gpio_set(dev, dev->board.tuner_gpio); + } /* set the mode to Analog mode initially */ cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 86ca8c2..f5a3e74 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1996,7 +1996,7 @@ static int cx25840_probe(struct i2c_client *client, state->volume = v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME, - 0, 65335, 65535 / 100, default_volume); + 0, 65535, 65535 / 100, default_volume); state->mute = v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 99dbae1..0fa85cb 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -17,7 +17,7 @@ config VIDEO_CX88 config VIDEO_CX88_ALSA tristate "Conexant 2388x DMA audio support" - depends on VIDEO_CX88 && SND && EXPERIMENTAL + depends on VIDEO_CX88 && SND select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio on diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index b984610..78abc1c 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -223,6 +223,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, usb_rcvintpipe(dev, ep->bEndpointAddress), buffer, buffer_len, int_irq, (void *)gspca_dev, interval); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; gspca_dev->int_urb = urb; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret < 0) { diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 83a718f..9052d57 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2357,8 +2357,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, (data[33] << 10); avg_lum >>= 9; atomic_set(&sd->avg_lum, avg_lum); - gspca_frame_add(gspca_dev, LAST_PACKET, - data, len); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); return; } if (gspca_dev->last_packet_type == LAST_PACKET) { diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index be03a71..f0316d0 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -466,6 +466,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar struct fb_vblank vblank; u32 trace; + memset(&vblank, 0, sizeof(struct fb_vblank)); + vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC; trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 4525335..a7210d9 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -239,7 +239,7 @@ static int device_process(struct m2mtest_ctx *ctx, return -EFAULT; } - if (in_buf->vb.size < out_buf->vb.size) { + if (in_buf->vb.size > out_buf->vb.size) { v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n"); return -EINVAL; } @@ -1014,6 +1014,7 @@ static int m2mtest_remove(struct platform_device *pdev) v4l2_m2m_release(dev->m2m_dev); del_timer_sync(&dev->timer); video_unregister_device(dev->vfd); + video_device_release(dev->vfd); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 758a4db..c71af4e 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -447,6 +447,9 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", __func__, rect.left, rect.top, rect.width, rect.height); + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + ret = mt9m111_make_rect(client, &rect); if (!ret) mt9m111->rect = rect; @@ -466,12 +469,14 @@ static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) { + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + a->bounds.left = MT9M111_MIN_DARK_COLS; a->bounds.top = MT9M111_MIN_DARK_ROWS; a->bounds.width = MT9M111_MAX_WIDTH; a->bounds.height = MT9M111_MAX_HEIGHT; a->defrect = a->bounds; - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; a->pixelaspect.numerator = 1; a->pixelaspect.denominator = 1; @@ -487,6 +492,7 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd, mf->width = mt9m111->rect.width; mf->height = mt9m111->rect.height; mf->code = mt9m111->fmt->code; + mf->colorspace = mt9m111->fmt->colorspace; mf->field = V4L2_FIELD_NONE; return 0; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index e7cd23c..b48473c 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -402,9 +402,6 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) return -EINVAL; break; - case 0: - /* No format change, only geometry */ - break; default: return -EINVAL; } diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 66ff174..b6ea672 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -378,6 +378,9 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, spin_lock_irqsave(&pcdev->lock, flags); + if (*fb_active == NULL) + goto out; + vb = &(*fb_active)->vb; dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -402,6 +405,7 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, *fb_active = buf; +out: spin_unlock_irqrestore(&pcdev->lock, flags); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 1b992b8..55ea914 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -513,7 +513,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, if (ret >= 0) { ret = pvr2_ctrl_range_check(cptr,*valptr); } - if (maskptr) *maskptr = ~0; + *maskptr = ~0; } else if (cptr->info->type == pvr2_ctl_bool) { ret = parse_token(ptr,len,valptr,boolNames, ARRAY_SIZE(boolNames)); @@ -522,7 +522,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, } else if (ret == 0) { *valptr = (*valptr & 1) ? !0 : 0; } - if (maskptr) *maskptr = 1; + *maskptr = 1; } else if (cptr->info->type == pvr2_ctl_enum) { ret = parse_token( ptr,len,valptr, @@ -531,7 +531,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, if (ret >= 0) { ret = pvr2_ctrl_range_check(cptr,*valptr); } - if (maskptr) *maskptr = ~0; + *maskptr = ~0; } else if (cptr->info->type == pvr2_ctl_bitmask) { ret = parse_tlist( ptr,len,maskptr,valptr, diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index b151c7b..6961c55 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -393,6 +393,37 @@ static void fimc_set_yuv_order(struct fimc_ctx *ctx) dbg("ctx->out_order_1p= %d", ctx->out_order_1p); } +static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) +{ + struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; + + f->dma_offset.y_h = f->offs_h; + if (!variant->pix_hoff) + f->dma_offset.y_h *= (f->fmt->depth >> 3); + + f->dma_offset.y_v = f->offs_v; + + f->dma_offset.cb_h = f->offs_h; + f->dma_offset.cb_v = f->offs_v; + + f->dma_offset.cr_h = f->offs_h; + f->dma_offset.cr_v = f->offs_v; + + if (!variant->pix_hoff) { + if (f->fmt->planes_cnt == 3) { + f->dma_offset.cb_h >>= 1; + f->dma_offset.cr_h >>= 1; + } + if (f->fmt->color == S5P_FIMC_YCBCR420) { + f->dma_offset.cb_v >>= 1; + f->dma_offset.cr_v >>= 1; + } + } + + dbg("in_offset: color= %d, y_h= %d, y_v= %d", + f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v); +} + /** * fimc_prepare_config - check dimensions, operation and color mode * and pre-calculate offset and the scaling coefficients. @@ -406,7 +437,6 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) { struct fimc_frame *s_frame, *d_frame; struct fimc_vid_buffer *buf = NULL; - struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; int ret = 0; s_frame = &ctx->s_frame; @@ -419,61 +449,16 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) swap(d_frame->width, d_frame->height); } - /* Prepare the output offset ratios for scaler. */ - d_frame->dma_offset.y_h = d_frame->offs_h; - if (!variant->pix_hoff) - d_frame->dma_offset.y_h *= (d_frame->fmt->depth >> 3); - - d_frame->dma_offset.y_v = d_frame->offs_v; - - d_frame->dma_offset.cb_h = d_frame->offs_h; - d_frame->dma_offset.cb_v = d_frame->offs_v; - - d_frame->dma_offset.cr_h = d_frame->offs_h; - d_frame->dma_offset.cr_v = d_frame->offs_v; + /* Prepare the DMA offset ratios for scaler. */ + fimc_prepare_dma_offset(ctx, &ctx->s_frame); + fimc_prepare_dma_offset(ctx, &ctx->d_frame); - if (!variant->pix_hoff && d_frame->fmt->planes_cnt == 3) { - d_frame->dma_offset.cb_h >>= 1; - d_frame->dma_offset.cb_v >>= 1; - d_frame->dma_offset.cr_h >>= 1; - d_frame->dma_offset.cr_v >>= 1; - } - - dbg("out offset: color= %d, y_h= %d, y_v= %d", - d_frame->fmt->color, - d_frame->dma_offset.y_h, d_frame->dma_offset.y_v); - - /* Prepare the input offset ratios for scaler. */ - s_frame->dma_offset.y_h = s_frame->offs_h; - if (!variant->pix_hoff) - s_frame->dma_offset.y_h *= (s_frame->fmt->depth >> 3); - s_frame->dma_offset.y_v = s_frame->offs_v; - - s_frame->dma_offset.cb_h = s_frame->offs_h; - s_frame->dma_offset.cb_v = s_frame->offs_v; - - s_frame->dma_offset.cr_h = s_frame->offs_h; - s_frame->dma_offset.cr_v = s_frame->offs_v; - - if (!variant->pix_hoff && s_frame->fmt->planes_cnt == 3) { - s_frame->dma_offset.cb_h >>= 1; - s_frame->dma_offset.cb_v >>= 1; - s_frame->dma_offset.cr_h >>= 1; - s_frame->dma_offset.cr_v >>= 1; - } - - dbg("in offset: color= %d, y_h= %d, y_v= %d", - s_frame->fmt->color, s_frame->dma_offset.y_h, - s_frame->dma_offset.y_v); - - fimc_set_yuv_order(ctx); - - /* Check against the scaler ratio. */ if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) || s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) { err("out of scaler range"); return -EINVAL; } + fimc_set_yuv_order(ctx); } /* Input DMA mode is not allowed when the scaler is disabled. */ @@ -822,7 +807,8 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f) } else { v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Wrong buffer/video queue type (%d)\n", f->type); - return -EINVAL; + ret = -EINVAL; + goto s_fmt_out; } pix = &f->fmt.pix; @@ -1414,8 +1400,10 @@ static int fimc_probe(struct platform_device *pdev) } fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev)); - if (!fimc->work_queue) + if (!fimc->work_queue) { + ret = -ENOMEM; goto err_irq; + } ret = fimc_register_m2m_device(fimc); if (ret) @@ -1492,6 +1480,7 @@ static struct samsung_fimc_variant fimc2_variant_s5p = { }; static struct samsung_fimc_variant fimc01_variant_s5pv210 = { + .pix_hoff = 1, .has_inp_rot = 1, .has_out_rot = 1, .min_inp_pixsize = 16, @@ -1506,6 +1495,7 @@ static struct samsung_fimc_variant fimc01_variant_s5pv210 = { }; static struct samsung_fimc_variant fimc2_variant_s5pv210 = { + .pix_hoff = 1, .min_inp_pixsize = 16, .min_out_pixsize = 32, diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ec697fc..bb8d83d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4323,13 +4323,13 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { /* Beholder Intl. Ltd. 2008 */ - /*Dmitry Belimov <d.belimov@gmail.com> */ - .name = "Beholder BeholdTV Columbus TVFM", + /* Dmitry Belimov <d.belimov@gmail.com> */ + .name = "Beholder BeholdTV Columbus TV/FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_ALPS_TSBE5_PAL, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, + .radio_type = TUNER_TEA5767, + .tuner_addr = 0xc2 >> 1, + .radio_addr = 0xc0 >> 1, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x000A8004, .inputs = {{ diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c index 5713f3a..ddd25d3 100644 --- a/drivers/media/video/saa7164/saa7164-buffer.c +++ b/drivers/media/video/saa7164/saa7164-buffer.c @@ -136,10 +136,11 @@ ret: int saa7164_buffer_dealloc(struct saa7164_tsport *port, struct saa7164_buffer *buf) { - struct saa7164_dev *dev = port->dev; + struct saa7164_dev *dev; - if ((buf == 0) || (port == 0)) + if (!buf || !port) return SAA_ERR_BAD_PARAMETER; + dev = port->dev; dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n", __func__, buf); diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 8bdd940..2ac85d8 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -486,6 +486,12 @@ static int uvc_parse_format(struct uvc_device *dev, max(frame->dwFrameInterval[0], frame->dwDefaultFrameInterval)); + if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { + frame->bFrameIntervalType = 1; + frame->dwFrameInterval[0] = + frame->dwDefaultFrameInterval; + } + uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n", frame->wWidth, frame->wHeight, 10000000/frame->dwDefaultFrameInterval, @@ -2026,6 +2032,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0 }, + /* Chicony CNF7129 (Asus EEE 100HE) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x04f2, + .idProduct = 0xb071, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_RESTRICT_FRAME_RATE }, /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -2091,6 +2106,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_PROBE_DEF }, + /* IMC Networks (Medion Akoya) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x13d3, + .idProduct = 0x5103, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* Syntek (HP Spartan) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index bdacf3b..892e0e5 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -182,6 +182,7 @@ struct uvc_xu_control { #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 #define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 #define UVC_QUIRK_PROBE_DEF 0x00000100 +#define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 372b87e..6ff9e4b 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -393,8 +393,10 @@ void videobuf_dma_contig_free(struct videobuf_queue *q, } /* read() method */ - dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle); - mem->vaddr = NULL; + if (mem->vaddr) { + dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle); + mem->vaddr = NULL; + } } EXPORT_SYMBOL_GPL(videobuf_dma_contig_free); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 06f9a9c..2ad0bc2 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -94,7 +94,7 @@ err: * must free the memory. */ static struct scatterlist *videobuf_pages_to_sg(struct page **pages, - int nr_pages, int offset) + int nr_pages, int offset, size_t size) { struct scatterlist *sglist; int i; @@ -110,12 +110,14 @@ static struct scatterlist *videobuf_pages_to_sg(struct page **pages, /* DMA to highmem pages might not work */ goto highmem; sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset); + size -= PAGE_SIZE - offset; for (i = 1; i < nr_pages; i++) { if (NULL == pages[i]) goto nopage; if (PageHighMem(pages[i])) goto highmem; - sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0); + sg_set_page(&sglist[i], pages[i], min(PAGE_SIZE, size), 0); + size -= min(PAGE_SIZE, size); } return sglist; @@ -170,7 +172,8 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, first = (data & PAGE_MASK) >> PAGE_SHIFT; last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; - dma->offset = data & ~PAGE_MASK; + dma->offset = data & ~PAGE_MASK; + dma->size = size; dma->nr_pages = last-first+1; dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL); if (NULL == dma->pages) @@ -252,7 +255,7 @@ int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) if (dma->pages) { dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, - dma->offset); + dma->offset, dma->size); } if (dma->vaddr) { dma->sglist = videobuf_vmalloc_to_sg(dma->vaddr, diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 04028a9..428377a 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -429,24 +429,25 @@ static void max8925_irq_sync_unlock(unsigned int irq) irq_tsc = cache_tsc; for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { irq_data = &max8925_irqs[i]; + /* 1 -- disable, 0 -- enable */ switch (irq_data->mask_reg) { case MAX8925_CHG_IRQ1_MASK: - irq_chg[0] &= irq_data->enable; + irq_chg[0] &= ~irq_data->enable; break; case MAX8925_CHG_IRQ2_MASK: - irq_chg[1] &= irq_data->enable; + irq_chg[1] &= ~irq_data->enable; break; case MAX8925_ON_OFF_IRQ1_MASK: - irq_on[0] &= irq_data->enable; + irq_on[0] &= ~irq_data->enable; break; case MAX8925_ON_OFF_IRQ2_MASK: - irq_on[1] &= irq_data->enable; + irq_on[1] &= ~irq_data->enable; break; case MAX8925_RTC_IRQ_MASK: - irq_rtc &= irq_data->enable; + irq_rtc &= ~irq_data->enable; break; case MAX8925_TSC_IRQ_MASK: - irq_tsc &= irq_data->enable; + irq_tsc &= ~irq_data->enable; break; default: dev_err(chip->dev, "wrong IRQ\n"); diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index 7dabe4d..294183b 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c @@ -394,8 +394,13 @@ static int wm831x_irq_set_type(unsigned int irq, unsigned int type) irq = irq - wm831x->irq_base; - if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) - return -EINVAL; + if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) { + /* Ignore internal-only IRQs */ + if (irq >= 0 && irq < WM831X_NUM_IRQS) + return 0; + else + return -EINVAL; + } switch (type) { case IRQ_TYPE_EDGE_BOTH: diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0b591b6..b743312 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -368,7 +368,7 @@ config VMWARE_BALLOON If unsure, say N. To compile this driver as a module, choose M here: the - module will be called vmware_balloon. + module will be called vmw_balloon. config ARM_CHARLCD bool "ARM Ltd. Character LCD Driver" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 255a80d..42eab95 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -33,5 +33,5 @@ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o obj-y += eeprom/ obj-y += cb710/ -obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o +obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 714c6b4..d5f3a3f 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -190,7 +190,6 @@ static int __devexit bh1780_remove(struct i2c_client *client) ddata = i2c_get_clientdata(client); sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group); - i2c_set_clientdata(client, NULL); kfree(ddata); return 0; diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmw_balloon.c index 2a1e804..2a1e804 100644 --- a/drivers/misc/vmware_balloon.c +++ b/drivers/misc/vmw_balloon.c diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 71ad416..aacb862 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -241,8 +241,10 @@ static struct sdhci_ops sdhci_s3c_ops = { static void sdhci_s3c_notify_change(struct platform_device *dev, int state) { struct sdhci_host *host = platform_get_drvdata(dev); + unsigned long flags; + if (host) { - spin_lock(&host->lock); + spin_lock_irqsave(&host->lock, flags); if (state) { dev_dbg(&dev->dev, "card inserted.\n"); host->flags &= ~SDHCI_DEVICE_DEAD; @@ -253,7 +255,7 @@ static void sdhci_s3c_notify_change(struct platform_device *dev, int state) host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; } tasklet_schedule(&host->card_tasklet); - spin_unlock(&host->lock); + spin_unlock_irqrestore(&host->lock, flags); } } @@ -481,8 +483,10 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) sdhci_remove_host(host, 1); for (ptr = 0; ptr < 3; ptr++) { - clk_disable(sc->clk_bus[ptr]); - clk_put(sc->clk_bus[ptr]); + if (sc->clk_bus[ptr]) { + clk_disable(sc->clk_bus[ptr]); + clk_put(sc->clk_bus[ptr]); + } } clk_disable(sc->clk_io); clk_put(sc->clk_io); diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index a382e3d..6fbeefa 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -682,7 +682,6 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) static int __devexit bf5xx_nand_remove(struct platform_device *pdev) { struct bf5xx_nand_info *info = to_nand_info(pdev); - struct mtd_info *mtd = NULL; platform_set_drvdata(pdev, NULL); @@ -690,11 +689,7 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) * and their partitions, then go through freeing the * resources used */ - mtd = &info->mtd; - if (mtd) { - nand_release(mtd); - kfree(mtd); - } + nand_release(&info->mtd); peripheral_free_list(bfin_nfc_pin_req); bf5xx_nand_dma_remove(info); @@ -710,7 +705,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd) struct nand_chip *chip = mtd->priv; int ret; - ret = nand_scan_ident(mtd, 1); + ret = nand_scan_ident(mtd, 1, NULL); if (ret) return ret; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index fcf8ceb..b2828e8 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -67,7 +67,9 @@ #define NFC_V1_V2_CONFIG1_BIG (1 << 5) #define NFC_V1_V2_CONFIG1_RST (1 << 6) #define NFC_V1_V2_CONFIG1_CE (1 << 7) -#define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9) +#define NFC_V2_CONFIG1_FP_INT (1 << 11) #define NFC_V1_V2_CONFIG2_INT (1 << 15) @@ -402,16 +404,16 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) /* Wait for operation to complete */ wait_op_done(host, true); + memcpy(host->data_buf, host->main_area0, 16); + if (this->options & NAND_BUSWIDTH_16) { - void __iomem *main_buf = host->main_area0; /* compress the ID info */ - writeb(readb(main_buf + 2), main_buf + 1); - writeb(readb(main_buf + 4), main_buf + 2); - writeb(readb(main_buf + 6), main_buf + 3); - writeb(readb(main_buf + 8), main_buf + 4); - writeb(readb(main_buf + 10), main_buf + 5); + host->data_buf[1] = host->data_buf[2]; + host->data_buf[2] = host->data_buf[4]; + host->data_buf[3] = host->data_buf[6]; + host->data_buf[4] = host->data_buf[8]; + host->data_buf[5] = host->data_buf[10]; } - memcpy(host->data_buf, host->main_area0, 16); } static uint16_t get_dev_status_v3(struct mxc_nand_host *host) @@ -729,27 +731,30 @@ static void preset_v1_v2(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp; - - /* enable interrupt, disable spare enable */ - tmp = readw(NFC_V1_V2_CONFIG1); - tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; - tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; - if (nand_chip->ecc.mode == NAND_ECC_HW) { - tmp |= NFC_V1_V2_CONFIG1_ECC_EN; - } else { - tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; - } + uint16_t config1 = 0; + + if (nand_chip->ecc.mode == NAND_ECC_HW) + config1 |= NFC_V1_V2_CONFIG1_ECC_EN; + + if (nfc_is_v21()) + config1 |= NFC_V2_CONFIG1_FP_INT; + + if (!cpu_is_mx21()) + config1 |= NFC_V1_V2_CONFIG1_INT_MSK; if (nfc_is_v21() && mtd->writesize) { + uint16_t pages_per_block = mtd->erasesize / mtd->writesize; + host->eccsize = get_eccsize(mtd); if (host->eccsize == 4) - tmp |= NFC_V2_CONFIG1_ECC_MODE_4; + config1 |= NFC_V2_CONFIG1_ECC_MODE_4; + + config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6); } else { host->eccsize = 1; } - writew(tmp, NFC_V1_V2_CONFIG1); + writew(config1, NFC_V1_V2_CONFIG1); /* preset operation */ /* Unlock the internal RAM Buffer */ diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 133d515..513e0a7 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -413,7 +413,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT); } while (prefetch_status); /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(); + gpmc_prefetch_reset(info->gpmc_cs); dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); return 0; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4d89f37..4d01cda6 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1320,6 +1320,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) goto fail_free_irq; } +#ifdef CONFIG_MTD_PARTITIONS if (mtd_has_cmdlinepart()) { static const char *probes[] = { "cmdlinepart", NULL }; struct mtd_partition *parts; @@ -1332,6 +1333,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) } return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); +#else + return 0; +#endif fail_free_irq: free_irq(irq, info); @@ -1364,7 +1368,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); del_mtd_device(mtd); +#ifdef CONFIG_MTD_PARTITIONS del_mtd_partitions(mtd); +#endif irq = platform_get_irq(pdev, 0); if (irq >= 0) free_irq(irq, info); diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index cb443af..a460f1b 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c @@ -554,14 +554,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) do { status = readl(base + S5PC110_DMA_TRANS_STATUS); + if (status & S5PC110_DMA_TRANS_STATUS_TE) { + writel(S5PC110_DMA_TRANS_CMD_TEC, + base + S5PC110_DMA_TRANS_CMD); + return -EIO; + } } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); - if (status & S5PC110_DMA_TRANS_STATUS_TE) { - writel(S5PC110_DMA_TRANS_CMD_TEC, base + S5PC110_DMA_TRANS_CMD); - writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); - return -EIO; - } - writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); return 0; @@ -571,13 +570,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, unsigned char *buffer, int offset, size_t count) { struct onenand_chip *this = mtd->priv; - void __iomem *bufferram; void __iomem *p; void *buf = (void *) buffer; dma_addr_t dma_src, dma_dst; int err; - p = bufferram = this->base + area; + p = this->base + area; if (ONENAND_CURRENT_BUFFERRAM(this)) { if (area == ONENAND_DATARAM) p += this->writesize; @@ -621,7 +619,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, normal: if (count != mtd->writesize) { /* Copy the bufferram to memory to prevent unaligned access */ - memcpy(this->page_buf, bufferram, mtd->writesize); + memcpy(this->page_buf, p, mtd->writesize); p = this->page_buf + offset; } diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 85671ad..179871d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -635,6 +635,9 @@ struct vortex_private { must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ large_frames:1, /* accept large frames */ handling_irq:1; /* private in_irq indicator */ + /* {get|set}_wol operations are already serialized by rtnl. + * no additional locking is required for the enable_wol and acpi_set_WOL() + */ int drv_flags; u16 status_enable; u16 intr_enable; @@ -2939,28 +2942,31 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct vortex_private *vp = netdev_priv(dev); - spin_lock_irq(&vp->lock); + if (!VORTEX_PCI(vp)) + return; + wol->supported = WAKE_MAGIC; wol->wolopts = 0; if (vp->enable_wol) wol->wolopts |= WAKE_MAGIC; - spin_unlock_irq(&vp->lock); } static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct vortex_private *vp = netdev_priv(dev); + + if (!VORTEX_PCI(vp)) + return -EOPNOTSUPP; + if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; - spin_lock_irq(&vp->lock); if (wol->wolopts & WAKE_MAGIC) vp->enable_wol = 1; else vp->enable_wol = 0; acpi_set_WOL(dev); - spin_unlock_irq(&vp->lock); return 0; } @@ -3202,6 +3208,9 @@ static void acpi_set_WOL(struct net_device *dev) return; } + if (VORTEX_PCI(vp)->current_state < PCI_D3hot) + return; + /* Change the power state to D3; RxEnable doesn't take effect. */ pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot); } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2cc81a5..77efe46 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2,6 +2,9 @@ # Network device configuration # +config HAVE_NET_MACB + bool + menuconfig NETDEVICES default y if UML depends on NET @@ -221,7 +224,7 @@ config MII config MACB tristate "Atmel MACB support" - depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 + depends on HAVE_NET_MACB select PHYLIB help The Atmel MACB ethernet interface is found on many AT32 and AT91 @@ -2428,7 +2431,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "Marvell Discovery (643XX) and Orion ethernet support" - depends on MV64X60 || PPC32 || PLAT_ORION + depends on (MV64X60 || PPC32 || PLAT_ORION) && INET select INET_LRO select PHYLIB help @@ -2803,7 +2806,7 @@ config NIU config PASEMI_MAC tristate "PA Semi 1/10Gbit MAC" - depends on PPC_PASEMI && PCI + depends on PPC_PASEMI && PCI && INET select PHYLIB select INET_LRO help diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 63b9ba0..c73be28 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -1251,6 +1251,12 @@ static void atl1_free_ring_resources(struct atl1_adapter *adapter) rrd_ring->desc = NULL; rrd_ring->dma = 0; + + adapter->cmb.dma = 0; + adapter->cmb.cmb = NULL; + + adapter->smb.dma = 0; + adapter->smb.smb = NULL; } static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) @@ -2847,10 +2853,11 @@ static int atl1_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); atl1_reset_hw(&adapter->hw); - adapter->cmb.cmb->int_stats = 0; - if (netif_running(netdev)) + if (netif_running(netdev)) { + adapter->cmb.cmb->int_stats = 0; atl1_up(adapter); + } netif_device_attach(netdev); return 0; diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 1e620e2..efeffdf 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -2170,8 +2170,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev, dev->irq = sdev->irq; SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); - netif_carrier_off(dev); - err = ssb_bus_powerup(sdev->bus, 0); if (err) { dev_err(sdev->dev, @@ -2213,6 +2211,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev, goto err_out_powerdown; } + netif_carrier_off(dev); + ssb_set_drvdata(sdev, dev); /* Chip reset provides power to the b44 MAC & PCI cores, which diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 822f586..0ddf4c6 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2466,6 +2466,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac if (!(dev->flags & IFF_MASTER)) goto out; + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) + goto out; + read_lock(&bond->lock); slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev), orig_dev); diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index c746b33..26bb118 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -362,6 +362,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct goto out; } + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) + goto out; + if (skb->len < sizeof(struct arp_pkt)) { pr_debug("Packet is too small to be an ARP\n"); goto out; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 3b16f62..e953c6a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5164,6 +5164,15 @@ int bond_create(struct net *net, const char *name) res = dev_alloc_name(bond_dev, "bond%d"); if (res < 0) goto out; + } else { + /* + * If we're given a name to register + * we need to ensure that its not already + * registered + */ + res = -EEXIST; + if (__dev_get_by_name(net, name) != NULL) + goto out; } res = register_netdevice(bond_dev); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index ad19585..f208712 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2296,6 +2296,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) case CHELSIO_GET_QSET_NUM:{ struct ch_reg edata; + memset(&edata, 0, sizeof(struct ch_reg)); + edata.cmd = CHELSIO_GET_QSET_NUM; edata.val = pi->nqsets; if (copy_to_user(useraddr, &edata, sizeof(edata))) diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 66ed08f..ba302a5 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -57,6 +57,7 @@ enum e1e_registers { E1000_SCTL = 0x00024, /* SerDes Control - RW */ E1000_FCAL = 0x00028, /* Flow Control Address Low - RW */ E1000_FCAH = 0x0002C, /* Flow Control Address High -RW */ + E1000_FEXTNVM4 = 0x00024, /* Future Extended NVM 4 - RW */ E1000_FEXTNVM = 0x00028, /* Future Extended NVM - RW */ E1000_FCT = 0x00030, /* Flow Control Type - RW */ E1000_VET = 0x00038, /* VLAN Ether Type - RW */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 63930d1..57b5435 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -105,6 +105,10 @@ #define E1000_FEXTNVM_SW_CONFIG 1 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */ +#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 +#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 +#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 + #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 @@ -125,6 +129,7 @@ /* SMBus Address Phy Register */ #define HV_SMB_ADDR PHY_REG(768, 26) +#define HV_SMB_ADDR_MASK 0x007F #define HV_SMB_ADDR_PEC_EN 0x0200 #define HV_SMB_ADDR_VALID 0x0080 @@ -237,6 +242,8 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); +static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); +static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -272,7 +279,7 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - u32 ctrl; + u32 ctrl, fwsm; s32 ret_val = 0; phy->addr = 1; @@ -294,7 +301,8 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) * disabled, then toggle the LANPHYPC Value bit to force * the interconnect to PCIe mode. */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { + fwsm = er32(FWSM); + if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) { ctrl = er32(CTRL); ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; @@ -303,6 +311,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; ew32(CTRL, ctrl); msleep(50); + + /* + * Gate automatic PHY configuration by hardware on + * non-managed 82579 + */ + if (hw->mac.type == e1000_pch2lan) + e1000_gate_hw_phy_config_ich8lan(hw, true); } /* @@ -315,6 +330,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) if (ret_val) goto out; + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(fwsm & E1000_ICH_FWSM_FW_VALID)) { + msleep(10); + e1000_gate_hw_phy_config_ich8lan(hw, false); + } + phy->id = e1000_phy_unknown; ret_val = e1000e_get_phy_id(hw); if (ret_val) @@ -561,13 +583,10 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) if (mac->type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - /* Disable PHY configuration by hardware, config by software */ - if (mac->type == e1000_pch2lan) { - u32 extcnf_ctrl = er32(EXTCNF_CTRL); - - extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - } + /* Gate automatic PHY configuration by hardware on managed 82579 */ + if ((mac->type == e1000_pch2lan) && + (er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); return 0; } @@ -652,6 +671,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) goto out; } + if (hw->mac.type == e1000_pch2lan) { + ret_val = e1000_k1_workaround_lv(hw); + if (ret_val) + goto out; + } + /* * Check if there was DownShift, must be checked * immediately after link-up @@ -895,6 +920,34 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) } /** + * e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states + * @hw: pointer to the HW structure + * + * Assumes semaphore already acquired. + * + **/ +static s32 e1000_write_smbus_addr(struct e1000_hw *hw) +{ + u16 phy_data; + u32 strap = er32(STRAP); + s32 ret_val = 0; + + strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; + + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~HV_SMB_ADDR_MASK; + phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); + phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); + +out: + return ret_val; +} + +/** * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration * @hw: pointer to the HW structure * @@ -903,7 +956,6 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) { - struct e1000_adapter *adapter = hw->adapter; struct e1000_phy_info *phy = &hw->phy; u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; s32 ret_val = 0; @@ -921,7 +973,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) if (phy->type != e1000_phy_igp_3) return ret_val; - if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) { + if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) || + (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) { sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; break; } @@ -961,21 +1014,16 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && - ((hw->mac.type == e1000_pchlan) || - (hw->mac.type == e1000_pch2lan))) { + if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && + (hw->mac.type == e1000_pchlan)) || + (hw->mac.type == e1000_pch2lan)) { /* * HW configures the SMBus address and LEDs when the * OEM and LCD Write Enable bits are set in the NVM. * When both NVM bits are cleared, SW will configure * them instead. */ - data = er32(STRAP); - data &= E1000_STRAP_SMBUS_ADDRESS_MASK; - reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; - reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, - reg_data); + ret_val = e1000_write_smbus_addr(hw); if (ret_val) goto out; @@ -1440,10 +1488,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; /* Enable jumbo frame workaround in the PHY */ - e1e_rphy(hw, PHY_REG(769, 20), &data); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); - if (ret_val) - goto out; e1e_rphy(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); data |= (0x37 << 5); @@ -1452,7 +1496,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; e1e_rphy(hw, PHY_REG(769, 16), &data); data &= ~(1 << 13); - data |= (1 << 12); ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); if (ret_val) goto out; @@ -1477,7 +1520,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) mac_reg = er32(RCTL); mac_reg &= ~E1000_RCTL_SECRC; - ew32(FFLT_DBG, mac_reg); + ew32(RCTL, mac_reg); ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, @@ -1503,17 +1546,12 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; /* Write PHY register values back to h/w defaults */ - e1e_rphy(hw, PHY_REG(769, 20), &data); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); - if (ret_val) - goto out; e1e_rphy(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); if (ret_val) goto out; e1e_rphy(hw, PHY_REG(769, 16), &data); - data &= ~(1 << 12); data |= (1 << 13); ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); if (ret_val) @@ -1559,6 +1597,69 @@ out: } /** + * e1000_k1_gig_workaround_lv - K1 Si workaround + * @hw: pointer to the HW structure + * + * Workaround to set the K1 beacon duration for 82579 parts + **/ +static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 status_reg = 0; + u32 mac_reg; + + if (hw->mac.type != e1000_pch2lan) + goto out; + + /* Set K1 beacon duration based on 1Gbps speed or otherwise */ + ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); + if (ret_val) + goto out; + + if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) + == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { + mac_reg = er32(FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; + + if (status_reg & HV_M_STATUS_SPEED_1000) + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; + else + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; + + ew32(FEXTNVM4, mac_reg); + } + +out: + return ret_val; +} + +/** + * e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware + * @hw: pointer to the HW structure + * @gate: boolean set to true to gate, false to ungate + * + * Gate/ungate the automatic PHY configuration via hardware; perform + * the configuration via software instead. + **/ +static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) +{ + u32 extcnf_ctrl; + + if (hw->mac.type != e1000_pch2lan) + return; + + extcnf_ctrl = er32(EXTCNF_CTRL); + + if (gate) + extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; + else + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; + + ew32(EXTCNF_CTRL, extcnf_ctrl); + return; +} + +/** * e1000_lan_init_done_ich8lan - Check for PHY config completion * @hw: pointer to the HW structure * @@ -1602,6 +1703,9 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) if (e1000_check_reset_block(hw)) goto out; + /* Allow time for h/w to get to quiescent state after reset */ + msleep(10); + /* Perform any necessary post-reset workarounds */ switch (hw->mac.type) { case e1000_pchlan: @@ -1630,6 +1734,13 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) /* Configure the LCD with the OEM bits in NVM */ ret_val = e1000_oem_bits_config_ich8lan(hw, true); + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { + msleep(10); + e1000_gate_hw_phy_config_ich8lan(hw, false); + } + out: return ret_val; } @@ -1646,6 +1757,11 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { s32 ret_val = 0; + /* Gate automatic PHY configuration by hardware on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); + ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) goto out; @@ -2910,6 +3026,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) * external PHY is reset. */ ctrl |= E1000_CTRL_PHY_RST; + + /* + * Gate automatic PHY configuration by hardware on + * non-managed 82579 + */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); } ret_val = e1000_acquire_swflag_ich8lan(hw); e_dbg("Issuing a global reset to ich8lan\n"); @@ -3460,13 +3584,20 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) { u32 phy_ctrl; + s32 ret_val; phy_ctrl = er32(PHY_CTRL); phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE; ew32(PHY_CTRL, phy_ctrl); - if (hw->mac.type >= e1000_pchlan) - e1000_phy_hw_reset_ich8lan(hw); + if (hw->mac.type >= e1000_pchlan) { + e1000_oem_bits_config_ich8lan(hw, true); + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return; + e1000_write_smbus_addr(hw); + hw->phy.ops.release(hw); + } } /** diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2b8ef44..e561d15 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2704,6 +2704,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) u32 psrctl = 0; u32 pages = 0; + /* Workaround Si errata on 82579 - configure jumbo frame flow */ + if (hw->mac.type == e1000_pch2lan) { + s32 ret_val; + + if (adapter->netdev->mtu > ETH_DATA_LEN) + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); + else + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); + } + /* Program MC offset vector base */ rctl = er32(RCTL); rctl &= ~(3 << E1000_RCTL_MO_SHIFT); @@ -2744,16 +2754,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) e1e_wphy(hw, 22, phy_data); } - /* Workaround Si errata on 82579 - configure jumbo frame flow */ - if (hw->mac.type == e1000_pch2lan) { - s32 ret_val; - - if (rctl & E1000_RCTL_LPE) - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); - else - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); - } - /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; @@ -4833,6 +4833,15 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } + /* Jumbo frame workaround on 82579 requires CRC be stripped */ + if ((adapter->hw.mac.type == e1000_pch2lan) && + !(adapter->flags2 & FLAG2_CRC_STRIPPING) && + (new_mtu > ETH_DATA_LEN)) { + e_err("Jumbo Frames not supported on 82579 when CRC " + "stripping is disabled.\n"); + return -EINVAL; + } + /* 82573 Errata 17 */ if (((adapter->hw.mac.type == e1000_82573) || (adapter->hw.mac.type == e1000_82574)) && diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index a333b42..6372610 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -533,8 +533,15 @@ static inline void ehea_fill_skb(struct net_device *dev, int length = cqe->num_bytes_transfered - 4; /*remove CRC */ skb_put(skb, length); - skb->ip_summed = CHECKSUM_UNNECESSARY; skb->protocol = eth_type_trans(skb, dev); + + /* The packet was not an IPV4 packet so a complemented checksum was + calculated. The value is found in the Internet Checksum field. */ + if (cqe->status & EHEA_CQE_BLIND_CKSUM) { + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = csum_unfold(~cqe->inet_checksum_value); + } else + skb->ip_summed = CHECKSUM_UNNECESSARY; } static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array, diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index f608a6c..3810473 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -150,6 +150,7 @@ struct ehea_rwqe { #define EHEA_CQE_TYPE_RQ 0x60 #define EHEA_CQE_STAT_ERR_MASK 0x700F #define EHEA_CQE_STAT_FAT_ERR_MASK 0xF +#define EHEA_CQE_BLIND_CKSUM 0x8000 #define EHEA_CQE_STAT_ERR_TCP 0x4000 #define EHEA_CQE_STAT_ERR_IP 0x2000 #define EHEA_CQE_STAT_ERR_CRC 0x1000 diff --git a/drivers/net/eql.c b/drivers/net/eql.c index dda2c79..0cb1cf9 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -555,6 +555,8 @@ static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mcp) equalizer_t *eql; master_config_t mc; + memset(&mc, 0, sizeof(master_config_t)); + if (eql_is_master(dev)) { eql = netdev_priv(dev); mc.max_slaves = eql->max_slaves; diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 768b840..cce32d4 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -678,24 +678,37 @@ static int fec_enet_mii_probe(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); struct phy_device *phy_dev = NULL; - int ret; + char mdio_bus_id[MII_BUS_ID_SIZE]; + char phy_name[MII_BUS_ID_SIZE + 3]; + int phy_id; fep->phy_dev = NULL; - /* find the first phy */ - phy_dev = phy_find_first(fep->mii_bus); - if (!phy_dev) { - printk(KERN_ERR "%s: no PHY found\n", dev->name); - return -ENODEV; + /* check for attached phy */ + for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { + if ((fep->mii_bus->phy_mask & (1 << phy_id))) + continue; + if (fep->mii_bus->phy_map[phy_id] == NULL) + continue; + if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) + continue; + strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); + break; } - /* attach the mac to the phy */ - ret = phy_connect_direct(dev, phy_dev, - &fec_enet_adjust_link, 0, - PHY_INTERFACE_MODE_MII); - if (ret) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return ret; + if (phy_id >= PHY_MAX_ADDR) { + printk(KERN_INFO "%s: no PHY, assuming direct connection " + "to switch\n", dev->name); + strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); + phy_id = 0; + } + + snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); + phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(phy_dev)) { + printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); + return PTR_ERR(phy_dev); } /* mask with MAC supported features */ @@ -738,7 +751,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) fep->mii_bus->read = fec_enet_mdio_read; fep->mii_bus->write = fec_enet_mdio_write; fep->mii_bus->reset = fec_enet_mdio_reset; - snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1); fep->mii_bus->priv = fep; fep->mii_bus->parent = &pdev->dev; @@ -1311,6 +1324,9 @@ fec_probe(struct platform_device *pdev) if (ret) goto failed_mii_init; + /* Carrier starts down, phylib will bring it up */ + netif_carrier_off(ndev); + ret = register_netdev(ndev); if (ret) goto failed_register; diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 3506fd6..519e19e 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2928,7 +2928,7 @@ static int __devinit emac_probe(struct platform_device *ofdev, if (dev->emac_irq != NO_IRQ) irq_dispose_mapping(dev->emac_irq); err_free: - kfree(ndev); + free_netdev(ndev); err_gone: /* if we were on the bootlist, remove us as we won't show up and * wake up all waiters to notify them in case they were waiting @@ -2971,7 +2971,7 @@ static int __devexit emac_remove(struct platform_device *ofdev) if (dev->emac_irq != NO_IRQ) irq_dispose_mapping(dev->emac_irq); - kfree(dev->ndev); + free_netdev(dev->ndev); return 0; } diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index bdf2149..87f0a93 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -38,6 +38,7 @@ #include <linux/of_device.h> #include <linux/of_mdio.h> #include <linux/of_platform.h> +#include <linux/of_address.h> #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/tcp.h> /* needed for sizeof(tcphdr) */ diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ll_temac_mdio.c index 5ae28c9..8cf9d4f 100644 --- a/drivers/net/ll_temac_mdio.c +++ b/drivers/net/ll_temac_mdio.c @@ -10,6 +10,7 @@ #include <linux/phy.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/of_address.h> #include <linux/slab.h> #include <linux/of_mdio.h> diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index cabae7b..b075a35 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1540,7 +1540,6 @@ netxen_process_rcv(struct netxen_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1602,8 +1601,6 @@ netxen_process_lro(struct netxen_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 49279b0..f9b509a 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -508,7 +508,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - int *has_shmem = priv_data; + int *priv = priv_data; + int try = (*priv & 0x1); int i; cistpl_io_t *io = &cfg->io; @@ -525,77 +526,103 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, i = p_dev->resource[1]->end = 0; } - *has_shmem = ((cfg->mem.nwin == 1) && - (cfg->mem.win[0].len >= 0x4000)); + *priv &= ((cfg->mem.nwin == 1) && + (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10; + p_dev->resource[0]->start = io->win[i].base; p_dev->resource[0]->end = io->win[i].len; - p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + if (!try) + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + else + p_dev->io_lines = 16; if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) return try_io_port(p_dev); - return 0; + return -EINVAL; +} + +static hw_info_t *pcnet_try_config(struct pcmcia_device *link, + int *has_shmem, int try) +{ + struct net_device *dev = link->priv; + hw_info_t *local_hw_info; + pcnet_dev_t *info = PRIV(dev); + int priv = try; + int ret; + + ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); + if (ret) { + dev_warn(&link->dev, "no useable port range found\n"); + return NULL; + } + *has_shmem = (priv & 0x10); + + if (!link->irq) + return NULL; + + if (resource_size(link->resource[1]) == 8) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + if ((link->manf_id == MANFID_IBM) && + (link->card_id == PRODID_IBM_HOME_AND_AWAY)) + link->conf.ConfigIndex |= 0x10; + + ret = pcmcia_request_configuration(link, &link->conf); + if (ret) + return NULL; + + dev->irq = link->irq; + dev->base_addr = link->resource[0]->start; + + if (info->flags & HAS_MISC_REG) { + if ((if_port == 1) || (if_port == 2)) + dev->if_port = if_port; + else + dev_notice(&link->dev, "invalid if_port requested\n"); + } else + dev->if_port = 0; + + if ((link->conf.ConfigBase == 0x03c0) && + (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { + dev_info(&link->dev, + "this is an AX88190 card - use axnet_cs instead.\n"); + return NULL; + } + + local_hw_info = get_hwinfo(link); + if (!local_hw_info) + local_hw_info = get_prom(link); + if (!local_hw_info) + local_hw_info = get_dl10019(link); + if (!local_hw_info) + local_hw_info = get_ax88190(link); + if (!local_hw_info) + local_hw_info = get_hwired(link); + + return local_hw_info; } static int pcnet_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; pcnet_dev_t *info = PRIV(dev); - int ret, start_pg, stop_pg, cm_offset; + int start_pg, stop_pg, cm_offset; int has_shmem = 0; hw_info_t *local_hw_info; dev_dbg(&link->dev, "pcnet_config\n"); - ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); - if (ret) - goto failed; - - if (!link->irq) - goto failed; - - if (resource_size(link->resource[1]) == 8) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - if ((link->manf_id == MANFID_IBM) && - (link->card_id == PRODID_IBM_HOME_AND_AWAY)) - link->conf.ConfigIndex |= 0x10; - - ret = pcmcia_request_configuration(link, &link->conf); - if (ret) - goto failed; - dev->irq = link->irq; - dev->base_addr = link->resource[0]->start; - if (info->flags & HAS_MISC_REG) { - if ((if_port == 1) || (if_port == 2)) - dev->if_port = if_port; - else - printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); - } else { - dev->if_port = 0; - } - - if ((link->conf.ConfigBase == 0x03c0) && - (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; - } - - local_hw_info = get_hwinfo(link); - if (local_hw_info == NULL) - local_hw_info = get_prom(link); - if (local_hw_info == NULL) - local_hw_info = get_dl10019(link); - if (local_hw_info == NULL) - local_hw_info = get_ax88190(link); - if (local_hw_info == NULL) - local_hw_info = get_hwired(link); - - if (local_hw_info == NULL) { - printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" - " address for io base %#3lx\n", dev->base_addr); - goto failed; + local_hw_info = pcnet_try_config(link, &has_shmem, 0); + if (!local_hw_info) { + /* check whether forcing io_lines to 16 helps... */ + pcmcia_disable_device(link); + local_hw_info = pcnet_try_config(link, &has_shmem, 1); + if (local_hw_info == NULL) { + dev_notice(&link->dev, "unable to read hardware net" + " address for io base %#3lx\n", dev->base_addr); + goto failed; + } } info->flags = local_hw_info->flags; diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 6a6b819..6c58da2 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -308,7 +308,7 @@ static int mdio_bus_suspend(struct device *dev) * may call phy routines that try to grab the same lock, and that may * lead to a deadlock. */ - if (phydev->attached_dev) + if (phydev->attached_dev && phydev->adjust_link) phy_stop_machine(phydev); if (!mdio_bus_phy_may_suspend(phydev)) @@ -331,7 +331,7 @@ static int mdio_bus_resume(struct device *dev) return ret; no_resume: - if (phydev->attached_dev) + if (phydev->attached_dev && phydev->adjust_link) phy_start_machine(phydev, NULL); return 0; diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6695a51..736b917 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1314,8 +1314,13 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; i = 0; list_for_each_entry(pch, &ppp->channels, clist) { - navail += pch->avail = (pch->chan != NULL); - pch->speed = pch->chan->speed; + if (pch->chan) { + pch->avail = 1; + navail++; + pch->speed = pch->chan->speed; + } else { + pch->avail = 0; + } if (pch->avail) { if (skb_queue_empty(&pch->file.xq) || !pch->had_frag) { diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 75ba744..2c7cf0b 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1316,7 +1316,7 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, return -ENOMEM; } - skb_reserve(skb, 2); + skb_reserve(skb, NET_IP_ALIGN); dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, PCI_DMA_FROMDEVICE); @@ -1404,7 +1404,6 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1466,8 +1465,6 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); @@ -1700,8 +1697,6 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); - if (!qlcnic_check_loopback_buff(skb->data)) adapter->diag_cnt++; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 078bbf4..992db2f 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1212,7 +1212,8 @@ static void rtl8169_update_counters(struct net_device *dev) if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) return; - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); + counters = dma_alloc_coherent(&tp->pci_dev->dev, sizeof(*counters), + &paddr, GFP_KERNEL); if (!counters) return; @@ -1233,7 +1234,8 @@ static void rtl8169_update_counters(struct net_device *dev) RTL_W32(CounterAddrLow, 0); RTL_W32(CounterAddrHigh, 0); - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); + dma_free_coherent(&tp->pci_dev->dev, sizeof(*counters), counters, + paddr); } static void rtl8169_get_ethtool_stats(struct net_device *dev, @@ -2934,7 +2936,7 @@ static const struct rtl_cfg_info { .hw_start = rtl_hw_start_8168, .region = 2, .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | + .intr_event = SYSErr | RxFIFOOver | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, @@ -3292,15 +3294,15 @@ static int rtl8169_open(struct net_device *dev) /* * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. + * dma_alloc_coherent provides more. */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); + tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, + &tp->TxPhyAddr, GFP_KERNEL); if (!tp->TxDescArray) goto err_pm_runtime_put; - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); + tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, + &tp->RxPhyAddr, GFP_KERNEL); if (!tp->RxDescArray) goto err_free_tx_0; @@ -3334,12 +3336,12 @@ out: err_release_ring_2: rtl8169_rx_clear(tp); err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, + tp->RxPhyAddr); tp->RxDescArray = NULL; err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, + tp->TxPhyAddr); tp->TxDescArray = NULL; err_pm_runtime_put: pm_runtime_put_noidle(&pdev->dev); @@ -3975,7 +3977,7 @@ static void rtl8169_free_rx_skb(struct rtl8169_private *tp, { struct pci_dev *pdev = tp->pci_dev; - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, + dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(*sk_buff); *sk_buff = NULL; @@ -4000,7 +4002,7 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev, struct RxDesc *desc, int rx_buf_sz, - unsigned int align) + unsigned int align, gfp_t gfp) { struct sk_buff *skb; dma_addr_t mapping; @@ -4008,13 +4010,13 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, pad = align ? align : NET_IP_ALIGN; - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); + skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); if (!skb) goto err_out; skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, + mapping = dma_map_single(&pdev->dev, skb->data, rx_buf_sz, PCI_DMA_FROMDEVICE); rtl8169_map_to_asic(desc, mapping, rx_buf_sz); @@ -4039,7 +4041,7 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp) } static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) + u32 start, u32 end, gfp_t gfp) { u32 cur; @@ -4054,7 +4056,7 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); + tp->rx_buf_sz, tp->align, gfp); if (!skb) break; @@ -4082,7 +4084,7 @@ static int rtl8169_init_ring(struct net_device *dev) memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) + if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) goto err_out; rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); @@ -4099,7 +4101,8 @@ static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, { unsigned int len = tx_skb->len; - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); + dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, + PCI_DMA_TODEVICE); desc->opts1 = 0x00; desc->opts2 = 0x00; desc->addr = 0x00; @@ -4243,7 +4246,8 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, txd = tp->TxDescArray + entry; len = frag->size; addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); + mapping = dma_map_single(&tp->pci_dev->dev, addr, len, + PCI_DMA_TODEVICE); /* anti gcc 2.95.3 bugware (sic) */ status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); @@ -4313,7 +4317,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->tx_skb[entry].skb = skb; } - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); + mapping = dma_map_single(&tp->pci_dev->dev, skb->data, len, + PCI_DMA_TODEVICE); tp->tx_skb[entry].len = len; txd->addr = cpu_to_le64(mapping); @@ -4477,8 +4482,8 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, if (!skb) goto out; - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); + dma_sync_single_for_cpu(&tp->pci_dev->dev, addr, pkt_size, + PCI_DMA_FROMDEVICE); skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); *sk_buff = skb; done = true; @@ -4549,11 +4554,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev, rtl8169_rx_csum(skb, desc); if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, + dma_sync_single_for_device(&pdev->dev, addr, pkt_size, PCI_DMA_FROMDEVICE); rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, + dma_unmap_single(&pdev->dev, addr, tp->rx_buf_sz, PCI_DMA_FROMDEVICE); tp->Rx_skbuff[entry] = NULL; } @@ -4583,7 +4588,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); + delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); if (!delta && count) netif_info(tp, intr, dev, "no Rx buffer allocated\n"); tp->dirty_rx += delta; @@ -4625,8 +4630,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) } /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + if (unlikely(status & RxFIFOOver)) { netif_stop_queue(dev); rtl8169_tx_timeout(dev); break; @@ -4770,10 +4774,10 @@ static int rtl8169_close(struct net_device *dev) free_irq(dev->irq, dev); - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, + tp->RxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, + tp->TxPhyAddr); tp->TxDescArray = NULL; tp->RxDescArray = NULL; diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 07eb884..44150f2 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -384,7 +384,7 @@ static void rionet_remove(struct rio_dev *rdev) free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0); unregister_netdev(ndev); - kfree(ndev); + free_netdev(ndev); list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { list_del(&peer->node); diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index cc4bd8c..9265315 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -804,7 +804,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev) err_out_free_page: free_page((unsigned long) sp->srings); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out: return err; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 40e5c46..465ae7e 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -43,6 +43,7 @@ #include <linux/seq_file.h> #include <linux/mii.h> #include <linux/slab.h> +#include <linux/dmi.h> #include <asm/irq.h> #include "skge.h" @@ -3868,6 +3869,8 @@ static void __devinit skge_show_addr(struct net_device *dev) netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); } +static int only_32bit_dma; + static int __devinit skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3889,7 +3892,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, pci_set_master(pdev); - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { + if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { using_dac = 1; err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { @@ -4147,8 +4150,21 @@ static struct pci_driver skge_driver = { .shutdown = skge_shutdown, }; +static struct dmi_system_id skge_32bit_dma_boards[] = { + { + .ident = "Gigabyte nForce boards", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"), + DMI_MATCH(DMI_BOARD_NAME, "nForce"), + }, + }, + {} +}; + static int __init skge_init_module(void) { + if (dmi_check_system(skge_32bit_dma_boards)) + only_32bit_dma = 1; skge_debug_init(); return pci_register_driver(&skge_driver); } diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 0909ae9..8150ba1 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -58,6 +58,7 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(SMSC_DRV_VERSION); +MODULE_ALIAS("platform:smsc911x"); #if USE_DEBUG > 0 static int debug = 16; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index bc3af78..1ec4b9e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4666,7 +4666,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) desc_idx, *post_ptr); drop_it_no_recycle: /* Other statistics kept track of by card. */ - tp->net_stats.rx_dropped++; + tp->rx_dropped++; goto next_pkt; } @@ -4726,7 +4726,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) if (len > (tp->dev->mtu + ETH_HLEN) && skb->protocol != htons(ETH_P_8021Q)) { dev_kfree_skb(skb); - goto next_pkt; + goto drop_it_no_recycle; } if (desc->type_flags & RXD_FLAG_VLAN && @@ -9240,6 +9240,8 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, stats->rx_missed_errors = old_stats->rx_missed_errors + get_stat64(&hw_stats->rx_discards); + stats->rx_dropped = tp->rx_dropped; + return stats; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 4937bd1..be7ff13 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2759,7 +2759,7 @@ struct tg3 { /* begin "everything else" cacheline(s) section */ - struct rtnl_link_stats64 net_stats; + unsigned long rx_dropped; struct rtnl_link_stats64 net_stats_prev; struct tg3_ethtool_stats estats; struct tg3_ethtool_stats estats_prev; diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 5efa577..6888e3d 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -243,6 +243,7 @@ enum { NWayState = (1 << 14) | (1 << 13) | (1 << 12), NWayRestart = (1 << 12), NonselPortActive = (1 << 9), + SelPortActive = (1 << 8), LinkFailStatus = (1 << 2), NetCxnErr = (1 << 1), }; @@ -363,7 +364,9 @@ static u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, }; /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/ static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; -static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; +static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; +/* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */ +static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; @@ -1064,6 +1067,9 @@ static void de21041_media_timer (unsigned long data) unsigned int carrier; unsigned long flags; + /* clear port active bits */ + dw32(SIAStatus, NonselPortActive | SelPortActive); + carrier = (status & NetCxnErr) ? 0 : 1; if (carrier) { @@ -1158,14 +1164,29 @@ no_link_yet: static void de_media_interrupt (struct de_private *de, u32 status) { if (status & LinkPass) { + /* Ignore if current media is AUI or BNC and we can't use TP */ + if ((de->media_type == DE_MEDIA_AUI || + de->media_type == DE_MEDIA_BNC) && + (de->media_lock || + !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))) + return; + /* If current media is not TP, change it to TP */ + if ((de->media_type == DE_MEDIA_AUI || + de->media_type == DE_MEDIA_BNC)) { + de->media_type = DE_MEDIA_TP_AUTO; + de_stop_rxtx(de); + de_set_media(de); + de_start_rxtx(de); + } de_link_up(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); return; } BUG_ON(!(status & LinkFail)); - - if (netif_carrier_ok(de->dev)) { + /* Mark the link as down only if current media is TP */ + if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI && + de->media_type != DE_MEDIA_BNC) { de_link_down(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); } @@ -1229,6 +1250,7 @@ static void de_adapter_sleep (struct de_private *de) if (de->de21040) return; + dw32(CSR13, 0); /* Reset phy */ pci_read_config_dword(de->pdev, PCIPM, &pmctl); pmctl |= PM_Sleep; pci_write_config_dword(de->pdev, PCIPM, pmctl); @@ -1574,12 +1596,15 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd) return 0; /* nothing to change */ de_link_down(de); + mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); de_stop_rxtx(de); de->media_type = new_media; de->media_lock = media_lock; de->media_advertise = ecmd->advertising; de_set_media(de); + if (netif_running(de->dev)) + de_start_rxtx(de); return 0; } @@ -1911,8 +1936,14 @@ fill_defaults: for (i = 0; i < DE_MAX_MEDIA; i++) { if (de->media[i].csr13 == 0xffff) de->media[i].csr13 = t21041_csr13[i]; - if (de->media[i].csr14 == 0xffff) - de->media[i].csr14 = t21041_csr14[i]; + if (de->media[i].csr14 == 0xffff) { + /* autonegotiation is broken at least on some chip + revisions - rev. 0x21 works, 0x11 does not */ + if (de->pdev->revision < 0x20) + de->media[i].csr14 = t21041_csr14_brk[i]; + else + de->media[i].csr14 = t21041_csr14[i]; + } if (de->media[i].csr15 == 0xffff) de->media[i].csr15 = t21041_csr15[i]; } @@ -2158,6 +2189,8 @@ static int de_resume (struct pci_dev *pdev) dev_err(&dev->dev, "pci_enable_device failed in resume\n"); goto out; } + pci_set_master(pdev); + de_init_rings(de); de_init_hw(de); out_attach: netif_device_attach(dev); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 6efca66..1cd752f 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1652,6 +1652,8 @@ static int hso_get_count(struct hso_serial *serial, struct uart_icount cnow; struct hso_tiocmget *tiocmget = serial->tiocmget; + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + if (!tiocmget) return -ENOENT; spin_lock_irq(&serial->serial_lock); diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 8cc9e31..1737d14 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c @@ -1244,16 +1244,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) int i, result; struct device *dev = i2400m_dev(i2400m); const struct i2400m_msg_hdr *msg_hdr; - size_t pl_itr, pl_size, skb_len; + size_t pl_itr, pl_size; unsigned long flags; - unsigned num_pls, single_last; + unsigned num_pls, single_last, skb_len; skb_len = skb->len; - d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n", + d_fnstart(4, dev, "(i2400m %p skb %p [size %u])\n", i2400m, skb, skb_len); result = -EIO; msg_hdr = (void *) skb->data; - result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len); + result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb_len); if (result < 0) goto error_msg_hdr_check; result = -EIO; @@ -1261,10 +1261,10 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */ num_pls * sizeof(msg_hdr->pld[0]); pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN); - if (pl_itr > skb->len) { /* got all the payload descriptors? */ + if (pl_itr > skb_len) { /* got all the payload descriptors? */ dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " "%u payload descriptors (%zu each, total %zu)\n", - skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr); + skb_len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr); goto error_pl_descr_short; } /* Walk each payload payload--check we really got it */ @@ -1272,7 +1272,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) /* work around old gcc warnings */ pl_size = i2400m_pld_size(&msg_hdr->pld[i]); result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i], - pl_itr, skb->len); + pl_itr, skb_len); if (result < 0) goto error_pl_descr_check; single_last = num_pls == 1 || i == num_pls - 1; @@ -1290,16 +1290,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) if (i < i2400m->rx_pl_min) i2400m->rx_pl_min = i; i2400m->rx_num++; - i2400m->rx_size_acc += skb->len; - if (skb->len < i2400m->rx_size_min) - i2400m->rx_size_min = skb->len; - if (skb->len > i2400m->rx_size_max) - i2400m->rx_size_max = skb->len; + i2400m->rx_size_acc += skb_len; + if (skb_len < i2400m->rx_size_min) + i2400m->rx_size_min = skb_len; + if (skb_len > i2400m->rx_size_max) + i2400m->rx_size_max = skb_len; spin_unlock_irqrestore(&i2400m->rx_lock, flags); error_pl_descr_check: error_pl_descr_short: error_msg_hdr_check: - d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n", + d_fnend(4, dev, "(i2400m %p skb %p [size %u]) = %d\n", i2400m, skb, skb_len, result); return result; } diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index cc648b6..a3d95cc 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -543,7 +543,7 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) if (conf_is_ht40(conf)) return clockrate * 2; - return clockrate * 2; + return clockrate; } static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9dd9e64..8fd00a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1411,7 +1411,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) clear_bit(STATUS_SCAN_HW, &priv->status); clear_bit(STATUS_SCANNING, &priv->status); /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->abort_scan); } int iwlagn_manage_ibss_station(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 07dbc27..e23c406 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2613,6 +2613,11 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; + if (test_bit(STATUS_SCANNING, &priv->status)) { + IWL_DEBUG_INFO(priv, "scan in progress.\n"); + return -EINVAL; + } + if (mode >= IWL_MAX_FORCE_RESET) { IWL_DEBUG_INFO(priv, "invalid reset request.\n"); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 59a308b..d31661c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3018,7 +3018,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) clear_bit(STATUS_SCANNING, &priv->status); /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->abort_scan); } static void iwl3945_bg_restart(struct work_struct *data) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index c3ceebb..4789f8e 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -71,6 +71,49 @@ #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) +/* page table handling */ +#define LEVEL_STRIDE (9) +#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) + +static inline int agaw_to_level(int agaw) +{ + return agaw + 2; +} + +static inline int agaw_to_width(int agaw) +{ + return 30 + agaw * LEVEL_STRIDE; +} + +static inline int width_to_agaw(int width) +{ + return (width - 30) / LEVEL_STRIDE; +} + +static inline unsigned int level_to_offset_bits(int level) +{ + return (level - 1) * LEVEL_STRIDE; +} + +static inline int pfn_level_offset(unsigned long pfn, int level) +{ + return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; +} + +static inline unsigned long level_mask(int level) +{ + return -1UL << level_to_offset_bits(level); +} + +static inline unsigned long level_size(int level) +{ + return 1UL << level_to_offset_bits(level); +} + +static inline unsigned long align_to_level(unsigned long pfn, int level) +{ + return (pfn + level_size(level) - 1) & level_mask(level); +} /* VT-d pages must always be _smaller_ than MM pages. Otherwise things are never going to work. */ @@ -434,8 +477,6 @@ void free_iova_mem(struct iova *iova) } -static inline int width_to_agaw(int width); - static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) { unsigned long sagaw; @@ -646,51 +687,6 @@ out: spin_unlock_irqrestore(&iommu->lock, flags); } -/* page table handling */ -#define LEVEL_STRIDE (9) -#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) - -static inline int agaw_to_level(int agaw) -{ - return agaw + 2; -} - -static inline int agaw_to_width(int agaw) -{ - return 30 + agaw * LEVEL_STRIDE; - -} - -static inline int width_to_agaw(int width) -{ - return (width - 30) / LEVEL_STRIDE; -} - -static inline unsigned int level_to_offset_bits(int level) -{ - return (level - 1) * LEVEL_STRIDE; -} - -static inline int pfn_level_offset(unsigned long pfn, int level) -{ - return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; -} - -static inline unsigned long level_mask(int level) -{ - return -1UL << level_to_offset_bits(level); -} - -static inline unsigned long level_size(int level) -{ - return 1UL << level_to_offset_bits(level); -} - -static inline unsigned long align_to_level(unsigned long pfn, int level) -{ - return (pfn + level_size(level) - 1) & level_mask(level); -} - static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, unsigned long pfn) { @@ -3761,6 +3757,33 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); +#define GGC 0x52 +#define GGC_MEMORY_SIZE_MASK (0xf << 8) +#define GGC_MEMORY_SIZE_NONE (0x0 << 8) +#define GGC_MEMORY_SIZE_1M (0x1 << 8) +#define GGC_MEMORY_SIZE_2M (0x3 << 8) +#define GGC_MEMORY_VT_ENABLED (0x8 << 8) +#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8) +#define GGC_MEMORY_SIZE_3M_VT (0xa << 8) +#define GGC_MEMORY_SIZE_4M_VT (0xb << 8) + +static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev) +{ + unsigned short ggc; + + if (pci_read_config_word(dev, GGC, &ggc)) + return; + + if (!(ggc & GGC_MEMORY_VT_ENABLED)) { + printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n"); + dmar_map_gfx = 0; + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); + /* On Tylersburg chipsets, some BIOSes have been known to enable the ISOCH DMAR unit for the Azalia sound device, but not give it any TLB entries, which causes it to deadlock. Check for that. We do diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index ce6a366..553d8ee 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -608,7 +608,7 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno, * the VF BAR size multiplied by the number of VFs. The alignment * is just the VF BAR size. */ -int pci_sriov_resource_alignment(struct pci_dev *dev, int resno) +resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) { struct resource tmp; enum pci_bar_type type; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 7754a67..6beb11b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -264,7 +264,8 @@ extern int pci_iov_init(struct pci_dev *dev); extern void pci_iov_release(struct pci_dev *dev); extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); -extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno); +extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, + int resno); extern void pci_restore_iov_state(struct pci_dev *dev); extern int pci_iov_bus_range(struct pci_bus *bus); @@ -320,7 +321,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev) } #endif /* CONFIG_PCI_IOV */ -static inline int pci_resource_alignment(struct pci_dev *dev, +static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, struct resource *res) { #ifdef CONFIG_PCI_IOV diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 89ed181..857ae01 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -163,6 +163,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs); /* + * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear + * for some HT machines to use C4 w/o hanging. + */ +static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev) +{ + u32 pmbase; + u16 pm1a; + + pci_read_config_dword(dev, 0x40, &pmbase); + pmbase = pmbase & 0xff80; + pm1a = inw(pmbase); + + if (pm1a & 0x10) { + dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n"); + outw(0x10, pmbase); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts); + +/* * Chipsets where PCI->PCI transfers vanish or hang */ static void __devinit quirk_nopcipci(struct pci_dev *dev) diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 54aa1c2..9ba4dad 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -163,7 +163,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev, c = p_dev->function_config; if (!(c->state & CONFIG_LOCKED)) { - dev_dbg(&s->dev, "Configuration isnt't locked\n"); + dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); mutex_unlock(&s->ops_mutex); return -EACCES; } @@ -220,7 +220,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, s->win[w].card_start = offset; ret = s->ops->set_mem_map(s, &s->win[w]); if (ret) - dev_warn(&s->dev, "failed to set_mem_map\n"); + dev_warn(&p_dev->dev, "failed to set_mem_map\n"); mutex_unlock(&s->ops_mutex); return ret; } /* pcmcia_map_mem_page */ @@ -244,18 +244,18 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, c = p_dev->function_config; if (!(s->state & SOCKET_PRESENT)) { - dev_dbg(&s->dev, "No card present\n"); + dev_dbg(&p_dev->dev, "No card present\n"); ret = -ENODEV; goto unlock; } if (!(c->state & CONFIG_LOCKED)) { - dev_dbg(&s->dev, "Configuration isnt't locked\n"); + dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); ret = -EACCES; goto unlock; } if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { - dev_dbg(&s->dev, + dev_dbg(&p_dev->dev, "changing Vcc or IRQ is not allowed at this time\n"); ret = -EINVAL; goto unlock; @@ -265,20 +265,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { if (mod->Vpp1 != mod->Vpp2) { - dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); + dev_dbg(&p_dev->dev, + "Vpp1 and Vpp2 must be the same\n"); ret = -EINVAL; goto unlock; } s->socket.Vpp = mod->Vpp1; if (s->ops->set_socket(s, &s->socket)) { - dev_printk(KERN_WARNING, &s->dev, + dev_printk(KERN_WARNING, &p_dev->dev, "Unable to set VPP\n"); ret = -EIO; goto unlock; } } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { - dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); + dev_dbg(&p_dev->dev, + "changing Vcc is not allowed at this time\n"); ret = -EINVAL; goto unlock; } @@ -401,7 +403,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) win = &s->win[w]; if (!(p_dev->_win & CLIENT_WIN_REQ(w))) { - dev_dbg(&s->dev, "not releasing unknown window\n"); + dev_dbg(&p_dev->dev, "not releasing unknown window\n"); mutex_unlock(&s->ops_mutex); return -EINVAL; } @@ -439,7 +441,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, return -ENODEV; if (req->IntType & INT_CARDBUS) { - dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); + dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n"); return -EINVAL; } @@ -447,7 +449,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, c = p_dev->function_config; if (c->state & CONFIG_LOCKED) { mutex_unlock(&s->ops_mutex); - dev_dbg(&s->dev, "Configuration is locked\n"); + dev_dbg(&p_dev->dev, "Configuration is locked\n"); return -EACCES; } @@ -455,7 +457,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, s->socket.Vpp = req->Vpp; if (s->ops->set_socket(s, &s->socket)) { mutex_unlock(&s->ops_mutex); - dev_printk(KERN_WARNING, &s->dev, + dev_printk(KERN_WARNING, &p_dev->dev, "Unable to set socket state\n"); return -EINVAL; } @@ -569,19 +571,20 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) int ret = -EINVAL; mutex_lock(&s->ops_mutex); - dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]); + dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR", + &c->io[0], &c->io[1]); if (!(s->state & SOCKET_PRESENT)) { - dev_dbg(&s->dev, "pcmcia_request_io: No card present\n"); + dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n"); goto out; } if (c->state & CONFIG_LOCKED) { - dev_dbg(&s->dev, "Configuration is locked\n"); + dev_dbg(&p_dev->dev, "Configuration is locked\n"); goto out; } if (c->state & CONFIG_IO_REQ) { - dev_dbg(&s->dev, "IO already configured\n"); + dev_dbg(&p_dev->dev, "IO already configured\n"); goto out; } @@ -592,7 +595,13 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) if (c->io[1].end) { ret = alloc_io_space(s, &c->io[1], p_dev->io_lines); if (ret) { + struct resource tmp = c->io[0]; + /* release the previously allocated resource */ release_io_space(s, &c->io[0]); + /* but preserve the settings, for they worked... */ + c->io[0].end = resource_size(&tmp); + c->io[0].start = tmp.start; + c->io[0].flags = tmp.flags; goto out; } } else @@ -601,7 +610,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) c->state |= CONFIG_IO_REQ; p_dev->_io = 1; - dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR", + dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR", &c->io[0], &c->io[1]); out: mutex_unlock(&s->ops_mutex); @@ -800,7 +809,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha int w; if (!(s->state & SOCKET_PRESENT)) { - dev_dbg(&s->dev, "No card present\n"); + dev_dbg(&p_dev->dev, "No card present\n"); return -ENODEV; } @@ -809,12 +818,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha req->Size = s->map_size; align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; if (req->Size & (s->map_size-1)) { - dev_dbg(&s->dev, "invalid map size\n"); + dev_dbg(&p_dev->dev, "invalid map size\n"); return -EINVAL; } if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || (req->Base & (align-1))) { - dev_dbg(&s->dev, "invalid base address\n"); + dev_dbg(&p_dev->dev, "invalid base address\n"); return -EINVAL; } if (req->Base) @@ -826,7 +835,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha if (!(s->state & SOCKET_WIN_REQ(w))) break; if (w == MAX_WIN) { - dev_dbg(&s->dev, "all windows are used already\n"); + dev_dbg(&p_dev->dev, "all windows are used already\n"); mutex_unlock(&s->ops_mutex); return -EINVAL; } @@ -837,7 +846,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha win->res = pcmcia_find_mem_region(req->Base, req->Size, align, 0, s); if (!win->res) { - dev_dbg(&s->dev, "allocating mem region failed\n"); + dev_dbg(&p_dev->dev, "allocating mem region failed\n"); mutex_unlock(&s->ops_mutex); return -EINVAL; } @@ -851,7 +860,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha win->card_start = 0; if (s->ops->set_mem_map(s, win) != 0) { - dev_dbg(&s->dev, "failed to set memory mapping\n"); + dev_dbg(&p_dev->dev, "failed to set memory mapping\n"); mutex_unlock(&s->ops_mutex); return -EIO; } @@ -874,7 +883,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha if (win->res) request_resource(&iomem_resource, res); - dev_dbg(&s->dev, "request_window results in %pR\n", res); + dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); mutex_unlock(&s->ops_mutex); *wh = res; diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index b8a869a..deef665 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -646,7 +646,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, if (!pci_resource_start(dev, 0)) { dev_warn(&dev->dev, "refusing to load the driver as the " "io_base is NULL.\n"); - goto err_out_free_mem; + goto err_out_disable; } dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx " diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 9024480..c44a5e8 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -51,7 +51,6 @@ * TODO: * - handle CPU hotplug * - provide turbo enable/disable api - * - make sure we can write turbo enable/disable reg based on MISC_EN * * Related documents: * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2 @@ -230,7 +229,7 @@ #define THM_TC2 0xac #define THM_DTV 0xb0 #define THM_ITV 0xd8 -#define ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */ +#define ITV_ME_SEQNO_MASK 0x00ff0000 /* ME should update every ~200ms */ #define ITV_ME_SEQNO_SHIFT (16) #define ITV_MCH_TEMP_MASK 0x0000ff00 #define ITV_MCH_TEMP_SHIFT (8) @@ -325,6 +324,7 @@ struct ips_driver { bool gpu_preferred; bool poll_turbo_status; bool second_cpu; + bool turbo_toggle_allowed; struct ips_mcp_limits *limits; /* Optional MCH interfaces for if i915 is in use */ @@ -415,7 +415,7 @@ static void ips_cpu_lower(struct ips_driver *ips) new_limit = cur_limit - 8; /* 1W decrease */ /* Clamp to SKU TDP limit */ - if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK)) + if (new_limit < (ips->orig_turbo_limit & TURBO_TDP_MASK)) new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK; thm_writew(THM_MPCPC, (new_limit * 10) / 8); @@ -461,7 +461,8 @@ static void ips_enable_cpu_turbo(struct ips_driver *ips) if (ips->__cpu_turbo_on) return; - on_each_cpu(do_enable_cpu_turbo, ips, 1); + if (ips->turbo_toggle_allowed) + on_each_cpu(do_enable_cpu_turbo, ips, 1); ips->__cpu_turbo_on = true; } @@ -498,7 +499,8 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips) if (!ips->__cpu_turbo_on) return; - on_each_cpu(do_disable_cpu_turbo, ips, 1); + if (ips->turbo_toggle_allowed) + on_each_cpu(do_disable_cpu_turbo, ips, 1); ips->__cpu_turbo_on = false; } @@ -598,17 +600,29 @@ static bool mcp_exceeded(struct ips_driver *ips) { unsigned long flags; bool ret = false; + u32 temp_limit; + u32 avg_power; + const char *msg = "MCP limit exceeded: "; spin_lock_irqsave(&ips->turbo_status_lock, flags); - if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100)) - ret = true; - if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit) + + temp_limit = ips->mcp_temp_limit * 100; + if (ips->mcp_avg_temp > temp_limit) { + dev_info(&ips->dev->dev, + "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp, + temp_limit); ret = true; - spin_unlock_irqrestore(&ips->turbo_status_lock, flags); + } - if (ret) + avg_power = ips->cpu_avg_power + ips->mch_avg_power; + if (avg_power > ips->mcp_power_limit) { dev_info(&ips->dev->dev, - "MCP power or thermal limit exceeded\n"); + "%sAvg power %u, limit %u\n", msg, avg_power, + ips->mcp_power_limit); + ret = true; + } + + spin_unlock_irqrestore(&ips->turbo_status_lock, flags); return ret; } @@ -663,6 +677,27 @@ static bool mch_exceeded(struct ips_driver *ips) } /** + * verify_limits - verify BIOS provided limits + * @ips: IPS structure + * + * BIOS can optionally provide non-default limits for power and temp. Check + * them here and use the defaults if the BIOS values are not provided or + * are otherwise unusable. + */ +static void verify_limits(struct ips_driver *ips) +{ + if (ips->mcp_power_limit < ips->limits->mcp_power_limit || + ips->mcp_power_limit > 35000) + ips->mcp_power_limit = ips->limits->mcp_power_limit; + + if (ips->mcp_temp_limit < ips->limits->core_temp_limit || + ips->mcp_temp_limit < ips->limits->mch_temp_limit || + ips->mcp_temp_limit > 150) + ips->mcp_temp_limit = min(ips->limits->core_temp_limit, + ips->limits->mch_temp_limit); +} + +/** * update_turbo_limits - get various limits & settings from regs * @ips: IPS driver struct * @@ -680,12 +715,21 @@ static void update_turbo_limits(struct ips_driver *ips) u32 hts = thm_readl(THM_HTS); ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS); - ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); + /* + * Disable turbo for now, until we can figure out why the power figures + * are wrong + */ + ips->cpu_turbo_enabled = false; + + if (ips->gpu_busy) + ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); + ips->core_power_limit = thm_readw(THM_MPCPC); ips->mch_power_limit = thm_readw(THM_MMGPC); ips->mcp_temp_limit = thm_readw(THM_PTL); ips->mcp_power_limit = thm_readw(THM_MPPC); + verify_limits(ips); /* Ignore BIOS CPU vs GPU pref */ } @@ -858,7 +902,7 @@ static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period) ret = (ret * 1000) / 65535; *last = val; - return ret; + return 0; } static const u16 temp_decay_factor = 2; @@ -940,7 +984,6 @@ static int ips_monitor(void *data) kfree(mch_samples); kfree(cpu_samples); kfree(mchp_samples); - kthread_stop(ips->adjust); return -ENOMEM; } @@ -948,7 +991,7 @@ static int ips_monitor(void *data) ITV_ME_SEQNO_SHIFT; seqno_timestamp = get_jiffies_64(); - old_cpu_power = thm_readl(THM_CEC) / 65535; + old_cpu_power = thm_readl(THM_CEC); schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); /* Collect an initial average */ @@ -1150,11 +1193,18 @@ static irqreturn_t ips_irq_handler(int irq, void *arg) STS_GPL_SHIFT; /* ignore EC CPU vs GPU pref */ ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS); - ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); + /* + * Disable turbo for now, until we can figure + * out why the power figures are wrong + */ + ips->cpu_turbo_enabled = false; + if (ips->gpu_busy) + ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); ips->mcp_temp_limit = (sts & STS_PTL_MASK) >> STS_PTL_SHIFT; ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >> STS_PPL_SHIFT; + verify_limits(ips); spin_unlock(&ips->turbo_status_lock); thm_writeb(THM_SEC, SEC_ACK); @@ -1333,8 +1383,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) * turbo manually or we'll get an illegal MSR access, even though * turbo will still be available. */ - if (!(misc_en & IA32_MISC_TURBO_EN)) - ; /* add turbo MSR write allowed flag if necessary */ + if (misc_en & IA32_MISC_TURBO_EN) + ips->turbo_toggle_allowed = true; + else + ips->turbo_toggle_allowed = false; if (strstr(boot_cpu_data.x86_model_id, "CPU M")) limits = &ips_sv_limits; @@ -1351,9 +1403,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) tdp = turbo_power & TURBO_TDP_MASK; /* Sanity check TDP against CPU */ - if (limits->mcp_power_limit != (tdp / 8) * 1000) { - dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n", - tdp / 8, limits->mcp_power_limit / 1000); + if (limits->core_power_limit != (tdp / 8) * 1000) { + dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n", + tdp / 8, limits->core_power_limit / 1000); + limits->core_power_limit = (tdp / 8) * 1000; } out: @@ -1390,7 +1443,7 @@ static bool ips_get_i915_syms(struct ips_driver *ips) return true; out_put_busy: - symbol_put(i915_gpu_turbo_disable); + symbol_put(i915_gpu_busy); out_put_lower: symbol_put(i915_gpu_lower); out_put_raise: @@ -1532,22 +1585,27 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) /* Save turbo limits & ratios */ rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); - ips_enable_cpu_turbo(ips); - ips->cpu_turbo_enabled = true; + ips_disable_cpu_turbo(ips); + ips->cpu_turbo_enabled = false; - /* Set up the work queue and monitor/adjust threads */ - ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); - if (IS_ERR(ips->monitor)) { + /* Create thermal adjust thread */ + ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); + if (IS_ERR(ips->adjust)) { dev_err(&dev->dev, - "failed to create thermal monitor thread, aborting\n"); + "failed to create thermal adjust thread, aborting\n"); ret = -ENOMEM; goto error_free_irq; + } - ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); - if (IS_ERR(ips->adjust)) { + /* + * Set up the work queue and monitor thread. The monitor thread + * will wake up ips_adjust thread. + */ + ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); + if (IS_ERR(ips->monitor)) { dev_err(&dev->dev, - "failed to create thermal adjust thread, aborting\n"); + "failed to create thermal monitor thread, aborting\n"); ret = -ENOMEM; goto error_thread_cleanup; } @@ -1566,7 +1624,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) return ret; error_thread_cleanup: - kthread_stop(ips->monitor); + kthread_stop(ips->adjust); error_free_irq: free_irq(ips->dev->irq, ips); error_unmap: diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e35ed12..2d61186 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3093,7 +3093,8 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = { TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */ }; -typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; +typedef u16 tpacpi_keymap_entry_t; +typedef tpacpi_keymap_entry_t tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; static int __init hotkey_init(struct ibm_init_struct *iibm) { @@ -3230,7 +3231,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) }; #define TPACPI_HOTKEY_MAP_SIZE sizeof(tpacpi_keymap_t) -#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_t[0]) +#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_entry_t) int res, i; int status; diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 936bae5..dc628cb 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c @@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_source source) empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; + break; case SOURCE_VOLTAGE: full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index c61ffec..2a10cd3 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c @@ -185,8 +185,8 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) { u32 data[3]; u8 *p = (u8 *)&data[1]; - int err = intel_scu_ipc_command(IPC_CMD_BATTERY_PROPERTY, - IPCMSG_BATTERY, NULL, 0, data, 3); + int err = intel_scu_ipc_command(IPCMSG_BATTERY, + IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3); prop->capacity = data[0]; prop->crnt = *p++; @@ -207,7 +207,7 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) static int pmic_scu_ipc_set_charger(int charger) { - return intel_scu_ipc_simple_command(charger, IPCMSG_BATTERY); + return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger); } /** diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 7d149a8..2ce2eb7 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -215,7 +215,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); int ret = -EINVAL; - if (info->vol_table && (index < (2 << info->vol_nbits))) { + if (info->vol_table && (index < (1 << info->vol_nbits))) { ret = info->vol_table[index]; if (info->slope_double) ret <<= 1; @@ -233,7 +233,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) max_uV = max_uV >> 1; } if (info->vol_table) { - for (i = 0; i < (2 << info->vol_nbits); i++) { + for (i = 0; i < (1 << info->vol_nbits); i++) { if (!info->vol_table[i]) break; if ((min_uV <= info->vol_table[i]) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 1179099..b349266 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -634,12 +634,9 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) "%s: failed to register regulator %s err %d\n", __func__, ab3100_regulator_desc[i].name, err); - i--; /* remove the already registered regulators */ - while (i > 0) { + while (--i >= 0) regulator_unregister(ab3100_regulators[i].rdev); - i--; - } return err; } diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index dc3f1a4..28c7ae6 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -157,7 +157,7 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) if (info->fixed_uV) return info->fixed_uV; - if (selector > info->voltages_len) + if (selector >= info->voltages_len) return -EINVAL; return info->supported_voltages[selector]; @@ -344,13 +344,14 @@ static inline struct ab8500_regulator_info *find_regulator_info(int id) static __devinit int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); - struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); + struct ab8500_platform_data *pdata; int i, err; if (!ab8500) { dev_err(&pdev->dev, "null mfd parent\n"); return -EINVAL; } + pdata = dev_get_platdata(ab8500->dev); /* register all regulators */ for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { @@ -368,11 +369,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); /* when we fail, un-register all earlier regulators */ - i--; - while (i > 0) { + while (--i >= 0) { info = &ab8500_regulator_info[i]; regulator_unregister(info->regulator); - i--; } return err; } diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index d59d2f2..a4be416 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -25,7 +25,7 @@ struct ad5398_chip_info { unsigned int current_level; unsigned int current_mask; unsigned int current_offset; - struct regulator_dev rdev; + struct regulator_dev *rdev; }; static int ad5398_calc_current(struct ad5398_chip_info *chip, @@ -211,7 +211,6 @@ MODULE_DEVICE_TABLE(i2c, ad5398_id); static int __devinit ad5398_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct regulator_dev *rdev; struct regulator_init_data *init_data = client->dev.platform_data; struct ad5398_chip_info *chip; const struct ad5398_current_data_format *df = @@ -233,9 +232,10 @@ static int __devinit ad5398_probe(struct i2c_client *client, chip->current_offset = df->current_offset; chip->current_mask = (chip->current_level - 1) << chip->current_offset; - rdev = regulator_register(&ad5398_reg, &client->dev, init_data, chip); - if (IS_ERR(rdev)) { - ret = PTR_ERR(rdev); + chip->rdev = regulator_register(&ad5398_reg, &client->dev, + init_data, chip); + if (IS_ERR(chip->rdev)) { + ret = PTR_ERR(chip->rdev); dev_err(&client->dev, "failed to register %s %s\n", id->name, ad5398_reg.name); goto err; @@ -254,9 +254,8 @@ static int __devexit ad5398_remove(struct i2c_client *client) { struct ad5398_chip_info *chip = i2c_get_clientdata(client); - regulator_unregister(&chip->rdev); + regulator_unregister(chip->rdev); kfree(chip); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 422a709..cc8b337 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -700,7 +700,7 @@ static void print_constraints(struct regulator_dev *rdev) constraints->min_uA != constraints->max_uA) { ret = _regulator_get_current_limit(rdev); if (ret > 0) - count += sprintf(buf + count, "at %d uA ", ret / 1000); + count += sprintf(buf + count, "at %d mA ", ret / 1000); } if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) @@ -2302,8 +2302,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); ret = device_register(&rdev->dev); - if (ret != 0) + if (ret != 0) { + put_device(&rdev->dev); goto clean; + } dev_set_drvdata(&rdev->dev, rdev); diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index e49d2bd..b8cc638 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -165,7 +165,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, mutex_init(&pmic->mtx); for (i = 0; i < 3; i++) { - pmic->rdev[i] = regulator_register(&isl_rd[0], &i2c->dev, + pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, init_data, pmic); if (IS_ERR(pmic->rdev[i])) { dev_err(&i2c->dev, "failed to register %s\n", id->name); @@ -191,8 +191,6 @@ static int __devexit isl6271a_remove(struct i2c_client *i2c) struct isl_pmic *pmic = i2c_get_clientdata(i2c); int i; - i2c_set_clientdata(i2c, NULL); - for (i = 0; i < 3; i++) regulator_unregister(pmic->rdev[i]); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 8867c27..559cfa2 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -121,14 +121,14 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) return -EINVAL; - if (min_uV >= 3000000) - selector = 3; - if (min_uV < 3000000) - selector = 2; - if (min_uV < 2500000) - selector = 1; if (min_uV < 1800000) selector = 0; + else if (min_uV < 2500000) + selector = 1; + else if (min_uV < 3000000) + selector = 2; + else if (min_uV >= 3000000) + selector = 3; if (max1586_v6_calc_voltage(selector) > max_uV) return -EINVAL; diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 4520ace..6b60a9c 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -330,7 +330,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, /* set external clock frequency */ info->extclk_freq = pdata->extclk_freq; max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK, - info->extclk_freq); + info->extclk_freq << 6); } if (pdata->ramp_timing) { diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index ab67298..a1baf1f 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -549,7 +549,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) if (!max8998) return -ENOMEM; - size = sizeof(struct regulator_dev *) * (pdata->num_regulators + 1); + size = sizeof(struct regulator_dev *) * pdata->num_regulators; max8998->rdev = kzalloc(size, GFP_KERNEL); if (!max8998->rdev) { kfree(max8998); @@ -557,7 +557,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) } rdev = max8998->rdev; + max8998->dev = &pdev->dev; max8998->iodev = iodev; + max8998->num_regulators = pdata->num_regulators; platform_set_drvdata(pdev, max8998); for (i = 0; i < pdata->num_regulators; i++) { @@ -583,7 +585,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) return 0; err: - for (i = 0; i <= max8998->num_regulators; i++) + for (i = 0; i < max8998->num_regulators; i++) if (rdev[i]) regulator_unregister(rdev[i]); @@ -599,7 +601,7 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev) struct regulator_dev **rdev = max8998->rdev; int i; - for (i = 0; i <= max8998->num_regulators; i++) + for (i = 0; i < max8998->num_regulators; i++) if (rdev[i]) regulator_unregister(rdev[i]); diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index c239f42..020f587 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -626,12 +626,6 @@ fail: return error; } -/** - * tps6507x_remove - TPS6507x driver i2c remove handler - * @client: i2c driver client device structure - * - * Unregister TPS driver as an i2c client device driver - */ static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 8cff141..51237fb 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -133,7 +133,7 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; val = (val & mask) >> ri->volt_shift; - if (val > ri->desc.n_voltages) + if (val >= ri->desc.n_voltages) BUG(); return ri->voltages[val] * 1000; @@ -150,7 +150,7 @@ static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, if (ret) return ret; - return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit); + return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); } static int tps6586x_regulator_enable(struct regulator_dev *rdev) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index e686cdb..9edf8f6 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -215,8 +215,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, case REGULATOR_MODE_IDLE: ret = wm831x_set_bits(wm831x, ctrl_reg, - WM831X_LDO1_LP_MODE, - WM831X_LDO1_LP_MODE); + WM831X_LDO1_LP_MODE, 0); if (ret < 0) return ret; @@ -225,10 +224,12 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, WM831X_LDO1_ON_MODE); if (ret < 0) return ret; + break; case REGULATOR_MODE_STANDBY: ret = wm831x_set_bits(wm831x, ctrl_reg, - WM831X_LDO1_LP_MODE, 0); + WM831X_LDO1_LP_MODE, + WM831X_LDO1_LP_MODE); if (ret < 0) return ret; diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 0e6ed7d..fe4b8a8 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1129,7 +1129,7 @@ static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev) mode = REGULATOR_MODE_NORMAL; } else if (!active && !sleep) mode = REGULATOR_MODE_IDLE; - else if (!sleep) + else if (sleep) mode = REGULATOR_MODE_STANDBY; return mode; diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c index d26780e..261a07e 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c @@ -235,6 +235,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) err = PTR_ERR(rtc); return err; } + platform_set_drvdata(pdev, rtc); return 0; } @@ -244,6 +245,7 @@ static int __exit ab3100_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; } diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 9daed8d..9de8516 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -268,7 +268,6 @@ out_irq: free_irq(client->irq, client); out_free: - i2c_set_clientdata(client, NULL); kfree(ds3232); return ret; } @@ -287,7 +286,6 @@ static int __devexit ds3232_remove(struct i2c_client *client) } rtc_device_unregister(ds3232->rtc); - i2c_set_clientdata(client, NULL); kfree(ds3232); return 0; } diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index a0d3ec8..f57a87f 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -310,11 +310,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) s3c_rtc_setaie(alrm->enabled); - if (alrm->enabled) - enable_irq_wake(s3c_rtc_alarmno); - else - disable_irq_wake(s3c_rtc_alarmno); - return 0; } @@ -587,6 +582,10 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) ticnt_en_save &= S3C64XX_RTCCON_TICEN; } s3c_rtc_enable(pdev, 0); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(s3c_rtc_alarmno); + return 0; } @@ -600,6 +599,10 @@ static int s3c_rtc_resume(struct platform_device *pdev) tmp = readb(s3c_rtc_base + S3C2410_RTCCON); writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); } + + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(s3c_rtc_alarmno); + return 0; } #else diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 6edf20b..2c7d2d9 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1154,7 +1154,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) dev_fsm, dev_fsm_len, GFP_KERNEL); if (priv->fsm == NULL) { CTCMY_DBF_DEV(SETUP, dev, "init_fsm error"); - kfree(dev); + free_netdev(dev); return NULL; } fsm_newstate(priv->fsm, DEV_STATE_STOPPED); @@ -1165,7 +1165,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) grp = ctcmpc_init_mpc_group(priv); if (grp == NULL) { MPC_DBF_DEV(SETUP, dev, "init_mpc_group error"); - kfree(dev); + free_netdev(dev); return NULL; } tasklet_init(&grp->mpc_tasklet2, diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 12900f7..3198c53 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -458,6 +458,7 @@ config SERIAL_SAMSUNG_UARTS int depends on ARM && PLAT_SAMSUNG default 2 if ARCH_S3C2400 + default 6 if ARCH_S5P6450 default 4 if SERIAL_SAMSUNG_UARTS_4 default 3 help @@ -526,12 +527,12 @@ config SERIAL_S3C24A0 Serial port support for the Samsung S3C24A0 SoC config SERIAL_S3C6400 - tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100) + tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100) select SERIAL_SAMSUNG_UARTS_4 default y help - Serial port support for the Samsung S3C6400, S3C6410, S5P6440 + Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450 and S5PC100 SoCs config SERIAL_S5PV210 diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 50441ff..2904aa0 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -472,14 +472,9 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, spin_unlock_irqrestore(&uap->port.lock, flags); } -static void pl010_set_ldisc(struct uart_port *port) +static void pl010_set_ldisc(struct uart_port *port, int new) { - int line = port->line; - - if (line >= port->state->port.tty->driver->num) - return; - - if (port->state->port.tty->ldisc->ops->num == N_PPS) { + if (new == N_PPS) { port->flags |= UPF_HARDPPS_CD; pl010_enable_ms(port); } else diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index bc9af50..5dff45c 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c @@ -27,6 +27,7 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> +#include <linux/slab.h> #include <linux/serial_reg.h> #include <linux/circ_buf.h> #include <linux/delay.h> @@ -1423,7 +1424,6 @@ static void hsu_global_init(void) } phsu = hsu; - hsu_debugfs_init(hsu); return; @@ -1435,18 +1435,20 @@ err_free_region: static void serial_hsu_remove(struct pci_dev *pdev) { - struct hsu_port *hsu; - int i; + void *priv = pci_get_drvdata(pdev); + struct uart_hsu_port *up; - hsu = pci_get_drvdata(pdev); - if (!hsu) + if (!priv) return; - for (i = 0; i < 3; i++) - uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port); + /* For port 0/1/2, priv is the address of uart_hsu_port */ + if (pdev->device != 0x081E) { + up = priv; + uart_remove_one_port(&serial_hsu_reg, &up->port); + } pci_set_drvdata(pdev, NULL); - free_irq(hsu->irq, hsu); + free_irq(pdev->irq, priv); pci_disable_device(pdev); } diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 8dedb26..c4399e2 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -500,6 +500,7 @@ static int __init mpc512x_psc_fifoc_init(void) psc_fifoc = of_iomap(np, 0); if (!psc_fifoc) { pr_err("%s: Can't map FIFOC\n", __func__); + of_node_put(np); return -ENODEV; } diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c index f6ad1ec..51c15f5 100644 --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c @@ -29,6 +29,7 @@ #include <linux/module.h> #include <linux/ioport.h> +#include <linux/irq.h> #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index b1156ba..7ac2bf5 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -1101,7 +1101,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); port->mapbase = res->start; - port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000); + port->membase = S3C_VA_UART + (res->start & 0xfffff); ret = platform_get_irq(platdev, 0); if (ret < 0) port->irq = 0; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 141c695..7d475b2 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -335,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - link->resource[0]->end = 8; link->conf.Attributes = CONF_ENABLE_IRQ; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -411,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, /*====================================================================*/ +static int pfc_config(struct pcmcia_device *p_dev) +{ + unsigned int port = 0; + struct serial_info *info = p_dev->priv; + + if ((p_dev->resource[1]->end != 0) && + (resource_size(p_dev->resource[1]) == 8)) { + port = p_dev->resource[1]->start; + info->slave = 1; + } else if ((info->manfid == MANFID_OSITECH) && + (resource_size(p_dev->resource[0]) == 0x40)) { + port = p_dev->resource[0]->start + 0x28; + info->slave = 1; + } + if (info->slave) + return setup_serial(p_dev, info, port, p_dev->irq); + + dev_warn(&p_dev->dev, "no usable port range found, giving up\n"); + return -ENODEV; +} + static int simple_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cf, cistpl_cftable_entry_t *dflt, @@ -461,23 +480,8 @@ static int simple_config(struct pcmcia_device *link) struct serial_info *info = link->priv; int i = -ENODEV, try; - /* If the card is already configured, look up the port and irq */ - if (link->function_config) { - unsigned int port = 0; - if ((link->resource[1]->end != 0) && - (resource_size(link->resource[1]) == 8)) { - port = link->resource[1]->end; - info->slave = 1; - } else if ((info->manfid == MANFID_OSITECH) && - (resource_size(link->resource[0]) == 0x40)) { - port = link->resource[0]->start + 0x28; - info->slave = 1; - } - if (info->slave) { - return setup_serial(link, info, port, - link->irq); - } - } + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 8; /* First pass: look for a config entry that looks normal. * Two tries: without IO aliases, then with aliases */ @@ -491,8 +495,7 @@ static int simple_config(struct pcmcia_device *link) if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) goto found_port; - printk(KERN_NOTICE - "serial_cs: no usable port range found, giving up\n"); + dev_warn(&link->dev, "no usable port range found, giving up\n"); return -1; found_port: @@ -558,6 +561,7 @@ static int multi_config(struct pcmcia_device *link) int i, base2 = 0; /* First, look for a generic full-sized window */ + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; link->resource[0]->end = info->multi * 8; if (pcmcia_loop_config(link, multi_config_check, &base2)) { /* If that didn't work, look for two windows */ @@ -565,15 +569,14 @@ static int multi_config(struct pcmcia_device *link) info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky, &base2)) { - printk(KERN_NOTICE "serial_cs: no usable port range" + dev_warn(&link->dev, "no usable port range " "found, giving up\n"); return -ENODEV; } } if (!link->irq) - dev_warn(&link->dev, - "serial_cs: no usable IRQ found, continuing...\n"); + dev_warn(&link->dev, "no usable IRQ found, continuing...\n"); /* * Apply any configuration quirks. @@ -675,6 +678,7 @@ static int serial_config(struct pcmcia_device * link) multifunction cards that ask for appropriate IO port ranges */ if ((info->multi == 0) && (link->has_func_id) && + (link->socket->pcmcia_pfc == 0) && ((link->func_id == CISTPL_FUNCID_MULTI) || (link->func_id == CISTPL_FUNCID_SERIAL))) pcmcia_loop_config(link, serial_check_for_multi, info); @@ -685,7 +689,13 @@ static int serial_config(struct pcmcia_device * link) if (info->quirk && info->quirk->multi != -1) info->multi = info->quirk->multi; - if (info->multi > 1) + dev_info(&link->dev, + "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n", + link->manf_id, link->card_id, + link->socket->pcmcia_pfc, info->multi, info->quirk); + if (link->socket->pcmcia_pfc) + i = pfc_config(link); + else if (info->multi > 1) i = multi_config(link); else i = simple_config(link); @@ -704,7 +714,7 @@ static int serial_config(struct pcmcia_device * link) return 0; failed: - dev_warn(&link->dev, "serial_cs: failed to initialize\n"); + dev_warn(&link->dev, "failed to initialize\n"); serial_remove(link); return -ENODEV; } diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index acd35d1..4c37c4e2 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -503,8 +503,9 @@ static void giveback(struct pl022 *pl022) msg->state = NULL; if (msg->complete) msg->complete(msg->context); - /* This message is completed, so let's turn off the clock! */ + /* This message is completed, so let's turn off the clocks! */ clk_disable(pl022->clk); + amba_pclk_disable(pl022->adev); } /** @@ -1139,9 +1140,10 @@ static void pump_messages(struct work_struct *work) /* Setup the SPI using the per chip configuration */ pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); /* - * We enable the clock here, then the clock will be disabled when + * We enable the clocks here, then the clocks will be disabled when * giveback() is called in each method (poll/interrupt/DMA) */ + amba_pclk_enable(pl022->adev); clk_enable(pl022->clk); restore_state(pl022); flush(pl022); @@ -1786,11 +1788,9 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) } /* Disable SSP */ - clk_enable(pl022->clk); writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); load_ssp_default_config(pl022); - clk_disable(pl022->clk); status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", pl022); @@ -1818,6 +1818,8 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) goto err_spi_register; } dev_dbg(dev, "probe succeded\n"); + /* Disable the silicon block pclk and clock it when needed */ + amba_pclk_disable(adev); return 0; err_spi_register: @@ -1879,9 +1881,9 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state) return status; } - clk_enable(pl022->clk); + amba_pclk_enable(adev); load_ssp_default_config(pl022); - clk_disable(pl022->clk); + amba_pclk_disable(adev); dev_dbg(&adev->dev, "suspended\n"); return 0; } @@ -1981,7 +1983,7 @@ static int __init pl022_init(void) return amba_driver_register(&pl022_driver); } -module_init(pl022_init); +subsys_initcall(pl022_init); static void __exit pl022_exit(void) { diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index d256cb0..5624785 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c @@ -181,10 +181,6 @@ static void flush(struct dw_spi *dws) wait_till_not_busy(dws); } -static void null_cs_control(u32 command) -{ -} - static int null_writer(struct dw_spi *dws) { u8 n_bytes = dws->n_bytes; @@ -322,7 +318,7 @@ static void giveback(struct dw_spi *dws) struct spi_transfer, transfer_list); - if (!last_transfer->cs_change) + if (!last_transfer->cs_change && dws->cs_control) dws->cs_control(MRST_SPI_DEASSERT); msg->state = NULL; @@ -396,6 +392,11 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) static irqreturn_t dw_spi_irq(int irq, void *dev_id) { struct dw_spi *dws = dev_id; + u16 irq_status, irq_mask = 0x3f; + + irq_status = dw_readw(dws, isr) & irq_mask; + if (!irq_status) + return IRQ_NONE; if (!dws->cur_msg) { spi_mask_intr(dws, SPI_INT_TXEI); @@ -544,13 +545,13 @@ static void pump_transfers(unsigned long data) */ if (dws->cs_control) { if (dws->rx && dws->tx) - chip->tmode = 0x00; + chip->tmode = SPI_TMOD_TR; else if (dws->rx) - chip->tmode = 0x02; + chip->tmode = SPI_TMOD_RO; else - chip->tmode = 0x01; + chip->tmode = SPI_TMOD_TO; - cr0 &= ~(0x3 << SPI_MODE_OFFSET); + cr0 &= ~SPI_TMOD_MASK; cr0 |= (chip->tmode << SPI_TMOD_OFFSET); } @@ -699,9 +700,6 @@ static int dw_spi_setup(struct spi_device *spi) chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); if (!chip) return -ENOMEM; - - chip->cs_control = null_cs_control; - chip->enable_dma = 0; } /* @@ -883,7 +881,7 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) dws->dma_inited = 0; dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); - ret = request_irq(dws->irq, dw_spi_irq, 0, + ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, "dw_spi", dws); if (ret < 0) { dev_err(&master->dev, "can not get IRQ\n"); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a9e5c79..b5a78a1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -23,6 +23,7 @@ #include <linux/init.h> #include <linux/cache.h> #include <linux/mutex.h> +#include <linux/of_device.h> #include <linux/slab.h> #include <linux/mod_devicetable.h> #include <linux/spi/spi.h> @@ -86,6 +87,10 @@ static int spi_match_device(struct device *dev, struct device_driver *drv) const struct spi_device *spi = to_spi_device(dev); const struct spi_driver *sdrv = to_spi_driver(drv); + /* Attempt an OF style match */ + if (of_driver_match_device(dev, drv)) + return 1; + if (sdrv->id_table) return !!spi_match_id(sdrv->id_table, spi); @@ -554,11 +559,9 @@ done: EXPORT_SYMBOL_GPL(spi_register_master); -static int __unregister(struct device *dev, void *master_dev) +static int __unregister(struct device *dev, void *null) { - /* note: before about 2.6.14-rc1 this would corrupt memory: */ - if (dev != master_dev) - spi_unregister_device(to_spi_device(dev)); + spi_unregister_device(to_spi_device(dev)); return 0; } @@ -576,8 +579,7 @@ void spi_unregister_master(struct spi_master *master) { int dummy; - dummy = device_for_each_child(master->dev.parent, &master->dev, - __unregister); + dummy = device_for_each_child(&master->dev, NULL, __unregister); device_unregister(&master->dev); } EXPORT_SYMBOL_GPL(spi_unregister_master); diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index e24a634..63e51b0 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c @@ -350,7 +350,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) spi_gpio->bitbang.master = spi_master_get(master); spi_gpio->bitbang.chipselect = spi_gpio_chipselect; - if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) { + if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index d31b57f..1dd86b8 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -408,11 +408,17 @@ static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) xfer_ofs = mspi->xfer_in_progress->len - mspi->count; - out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); + if (mspi->rx_dma == mspi->dma_dummy_rx) + out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma); + else + out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); out_be16(&rx_bd->cbd_datlen, 0); out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP); - out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); + if (mspi->tx_dma == mspi->dma_dummy_tx) + out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma); + else + out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); out_be16(&tx_bd->cbd_datlen, xfer_len); out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | BD_SC_LAST); diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c index 9736581..c3038da 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi_s3c64xx.c @@ -200,6 +200,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) val = readl(regs + S3C64XX_SPI_STATUS); } while (TX_FIFO_LVL(val, sci) && loops--); + if (loops == 0) + dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n"); + /* Flush RxFIFO*/ loops = msecs_to_loops(1); do { @@ -210,6 +213,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) break; } while (loops--); + if (loops == 0) + dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n"); + val = readl(regs + S3C64XX_SPI_CH_CFG); val &= ~S3C64XX_SPI_CH_SW_RST; writel(val, regs + S3C64XX_SPI_CH_CFG); @@ -320,16 +326,17 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, /* millisecs to xfer 'len' bytes @ 'cur_speed' */ ms = xfer->len * 8 * 1000 / sdd->cur_speed; - ms += 5; /* some tolerance */ + ms += 10; /* some tolerance */ if (dma_mode) { val = msecs_to_jiffies(ms) + 10; val = wait_for_completion_timeout(&sdd->xfer_completion, val); } else { + u32 status; val = msecs_to_loops(ms); do { - val = readl(regs + S3C64XX_SPI_STATUS); - } while (RX_FIFO_LVL(val, sci) < xfer->len && --val); + status = readl(regs + S3C64XX_SPI_STATUS); + } while (RX_FIFO_LVL(status, sci) < xfer->len && --val); } if (!val) @@ -447,8 +454,8 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) writel(val, regs + S3C64XX_SPI_CLK_CFG); } -void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, - int size, enum s3c2410_dma_buffresult res) +static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, + int size, enum s3c2410_dma_buffresult res) { struct s3c64xx_spi_driver_data *sdd = buf_id; unsigned long flags; @@ -467,8 +474,8 @@ void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, spin_unlock_irqrestore(&sdd->lock, flags); } -void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, - int size, enum s3c2410_dma_buffresult res) +static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, + int size, enum s3c2410_dma_buffresult res) { struct s3c64xx_spi_driver_data *sdd = buf_id; unsigned long flags; @@ -508,8 +515,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (xfer->tx_buf != NULL) { - xfer->tx_dma = dma_map_single(dev, xfer->tx_buf, - xfer->len, DMA_TO_DEVICE); + xfer->tx_dma = dma_map_single(dev, + (void *)xfer->tx_buf, xfer->len, + DMA_TO_DEVICE); if (dma_mapping_error(dev, xfer->tx_dma)) { dev_err(dev, "dma_map_single Tx failed\n"); xfer->tx_dma = XFER_DMAADDR_INVALID; @@ -919,6 +927,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) return -ENODEV; } + sci = pdev->dev.platform_data; + if (!sci->src_clk_name) { + dev_err(&pdev->dev, + "Board init must call s3c64xx_spi_set_info()\n"); + return -EINVAL; + } + /* Check for availability of necessary resource */ dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -946,8 +961,6 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) return -ENOMEM; } - sci = pdev->dev.platform_data; - platform_set_drvdata(pdev, master); sdd = spi_master_get_devdata(master); @@ -1170,7 +1183,7 @@ static int __init s3c64xx_spi_init(void) { return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); } -module_init(s3c64xx_spi_init); +subsys_initcall(s3c64xx_spi_init); static void __exit s3c64xx_spi_exit(void) { diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index baa8b05..6e973a7 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -30,7 +30,6 @@ #include "hash.h" #include <linux/if_arp.h> -#include <linux/netfilter_bridge.h> #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -431,11 +430,6 @@ out: return NOTIFY_DONE; } -static int batman_skb_recv_finish(struct sk_buff *skb) -{ - return NF_ACCEPT; -} - /* receive a packet with the batman ethertype coming on a hard * interface */ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, @@ -456,13 +450,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (atomic_read(&module_state) != MODULE_ACTIVE) goto err_free; - /* if netfilter/ebtables wants to block incoming batman - * packets then give them a chance to do so here */ - ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL, - batman_skb_recv_finish); - if (ret != 1) - goto err_out; - /* packet should hold at least type and version */ if (unlikely(skb_headlen(skb) < 2)) goto err_free; diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 055edee..da3c82e4 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -29,7 +29,6 @@ #include "vis.h" #include "aggregation.h" -#include <linux/netfilter_bridge.h> static void send_outstanding_bcast_packet(struct work_struct *work); @@ -92,12 +91,9 @@ int send_skb_packet(struct sk_buff *skb, /* dev_queue_xmit() returns a negative result on error. However on * congestion and traffic shaping, it drops and returns NET_XMIT_DROP - * (which is > 0). This will not be treated as an error. - * Also, if netfilter/ebtables wants to block outgoing batman - * packets then giving them a chance to do so here */ + * (which is > 0). This will not be treated as an error. */ - return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, - dev_queue_xmit); + return dev_queue_xmit(skb); send_skb_err: kfree_skb(skb); return NET_XMIT_DROP; diff --git a/drivers/staging/ti-st/st.h b/drivers/staging/ti-st/st.h index 9952579..1b3060e 100644 --- a/drivers/staging/ti-st/st.h +++ b/drivers/staging/ti-st/st.h @@ -80,5 +80,4 @@ struct st_proto_s { extern long st_register(struct st_proto_s *); extern long st_unregister(enum proto_type); -extern struct platform_device *st_get_plat_device(void); #endif /* ST_H */ diff --git a/drivers/staging/ti-st/st_core.c b/drivers/staging/ti-st/st_core.c index 063c9b1..b85d8bf 100644 --- a/drivers/staging/ti-st/st_core.c +++ b/drivers/staging/ti-st/st_core.c @@ -38,7 +38,6 @@ #include "st_ll.h" #include "st.h" -#define VERBOSE /* strings to be used for rfkill entries and by * ST Core to be used for sysfs debug entry */ @@ -581,7 +580,7 @@ long st_register(struct st_proto_s *new_proto) long err = 0; unsigned long flags = 0; - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); pr_info("%s(%d) ", __func__, new_proto->type); if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL || new_proto->reg_complete_cb == NULL) { @@ -713,7 +712,7 @@ long st_unregister(enum proto_type type) pr_debug("%s: %d ", __func__, type); - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); if (type < ST_BT || type >= ST_MAX) { pr_err(" protocol %d not supported", type); return -EPROTONOSUPPORT; @@ -767,7 +766,7 @@ long st_write(struct sk_buff *skb) #endif long len; - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); if (unlikely(skb == NULL || st_gdata == NULL || st_gdata->tty == NULL)) { pr_err("data/tty unavailable to perform write"); @@ -818,7 +817,7 @@ static int st_tty_open(struct tty_struct *tty) struct st_data_s *st_gdata; pr_info("%s ", __func__); - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); st_gdata->tty = tty; tty->disc_data = st_gdata; diff --git a/drivers/staging/ti-st/st_core.h b/drivers/staging/ti-st/st_core.h index e0c32d1..8601320 100644 --- a/drivers/staging/ti-st/st_core.h +++ b/drivers/staging/ti-st/st_core.h @@ -117,7 +117,7 @@ int st_core_init(struct st_data_s **); void st_core_exit(struct st_data_s *); /* ask for reference from KIM */ -void st_kim_ref(struct st_data_s **); +void st_kim_ref(struct st_data_s **, int); #define GPS_STUB_TEST #ifdef GPS_STUB_TEST diff --git a/drivers/staging/ti-st/st_kim.c b/drivers/staging/ti-st/st_kim.c index b4a6c7f..9e99463 100644 --- a/drivers/staging/ti-st/st_kim.c +++ b/drivers/staging/ti-st/st_kim.c @@ -72,11 +72,26 @@ const unsigned char *protocol_names[] = { PROTO_ENTRY(ST_GPS, "GPS"), }; +#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ +struct platform_device *st_kim_devices[MAX_ST_DEVICES]; /**********************************************************************/ /* internal functions */ /** + * st_get_plat_device - + * function which returns the reference to the platform device + * requested by id. As of now only 1 such device exists (id=0) + * the context requesting for reference can get the id to be + * requested by a. The protocol driver which is registering or + * b. the tty device which is opened. + */ +static struct platform_device *st_get_plat_device(int id) +{ + return st_kim_devices[id]; +} + +/** * validate_firmware_response - * function to return whether the firmware response was proper * in case of error don't complete so that waiting for proper @@ -353,7 +368,7 @@ void st_kim_chip_toggle(enum proto_type type, enum kim_gpio_state state) struct kim_data_s *kim_gdata; pr_info(" %s ", __func__); - kim_pdev = st_get_plat_device(); + kim_pdev = st_get_plat_device(0); kim_gdata = dev_get_drvdata(&kim_pdev->dev); if (kim_gdata->gpios[type] == -1) { @@ -574,12 +589,12 @@ static int kim_toggle_radio(void *data, bool blocked) * This would enable multiple such platform devices to exist * on a given platform */ -void st_kim_ref(struct st_data_s **core_data) +void st_kim_ref(struct st_data_s **core_data, int id) { struct platform_device *pdev; struct kim_data_s *kim_gdata; /* get kim_gdata reference from platform device */ - pdev = st_get_plat_device(); + pdev = st_get_plat_device(id); kim_gdata = dev_get_drvdata(&pdev->dev); *core_data = kim_gdata->core_data; } @@ -623,6 +638,7 @@ static int kim_probe(struct platform_device *pdev) long *gpios = pdev->dev.platform_data; struct kim_data_s *kim_gdata; + st_kim_devices[pdev->id] = pdev; kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_ATOMIC); if (!kim_gdata) { pr_err("no mem to allocate"); diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig index c725356..de7ebb9 100644 --- a/drivers/staging/tm6000/Kconfig +++ b/drivers/staging/tm6000/Kconfig @@ -1,6 +1,6 @@ config VIDEO_TM6000 tristate "TV Master TM5600/6000/6010 driver" - depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL + depends on VIDEO_DEV && I2C && INPUT && IR_CORE && USB && EXPERIMENTAL select VIDEO_TUNER select MEDIA_TUNER_XC2028 select MEDIA_TUNER_XC5000 diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 32f7a0a..54f7667 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -46,7 +46,7 @@ MODULE_PARM_DESC(enable_ir, "enable ir (default is enable"); } struct tm6000_ir_poll_result { - u8 rc_data[4]; + u16 rc_data; }; struct tm6000_IR { @@ -60,9 +60,9 @@ struct tm6000_IR { int polling; struct delayed_work work; u8 wait:1; + u8 key:1; struct urb *int_urb; u8 *urb_data; - u8 key:1; int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); @@ -122,13 +122,14 @@ static void tm6000_ir_urb_received(struct urb *urb) if (urb->status != 0) printk(KERN_INFO "not ready\n"); - else if (urb->actual_length > 0) + else if (urb->actual_length > 0) { memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length); - dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], - ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); + dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], + ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); - ir->key = 1; + ir->key = 1; + } rc = usb_submit_urb(urb, GFP_ATOMIC); } @@ -140,30 +141,47 @@ static int default_polling_getkey(struct tm6000_IR *ir, int rc; u8 buf[2]; - if (ir->wait && !&dev->int_in) { - poll_result->rc_data[0] = 0xff; + if (ir->wait && !&dev->int_in) return 0; - } if (&dev->int_in) { - poll_result->rc_data[0] = ir->urb_data[0]; - poll_result->rc_data[1] = ir->urb_data[1]; + if (ir->ir.ir_type == IR_TYPE_RC5) + poll_result->rc_data = ir->urb_data[0]; + else + poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; } else { tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); msleep(10); tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); msleep(10); - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1); + if (ir->ir.ir_type == IR_TYPE_RC5) { + rc = tm6000_read_write_usb(dev, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + REQ_02_GET_IR_CODE, 0, 0, buf, 1); - msleep(10); + msleep(10); - dprintk("read data=%02x\n", buf[0]); - if (rc < 0) - return rc; + dprintk("read data=%02x\n", buf[0]); + if (rc < 0) + return rc; - poll_result->rc_data[0] = buf[0]; + poll_result->rc_data = buf[0]; + } else { + rc = tm6000_read_write_usb(dev, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + REQ_02_GET_IR_CODE, 0, 0, buf, 2); + + msleep(10); + + dprintk("read data=%04x\n", buf[0] | buf[1] << 8); + if (rc < 0) + return rc; + + poll_result->rc_data = buf[0] | buf[1] << 8; + } + if ((poll_result->rc_data & 0x00ff) != 0xff) + ir->key = 1; } return 0; } @@ -180,12 +198,11 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) return; } - dprintk("ir->get_key result data=%02x %02x\n", - poll_result.rc_data[0], poll_result.rc_data[1]); + dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); - if (poll_result.rc_data[0] != 0xff && ir->key == 1) { + if (ir->key) { ir_input_keydown(ir->input->input_dev, &ir->ir, - poll_result.rc_data[0] | poll_result.rc_data[1] << 8); + (u32)poll_result.rc_data); ir_input_nokey(ir->input->input_dev, &ir->ir); ir->key = 0; diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index 0142338b..4bdb836 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -766,9 +766,14 @@ static int wpa_set_associate(PSDevice pDevice, DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); - if (param->u.wpa_associate.wpa_ie && - copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) - return -EINVAL; + if (param->u.wpa_associate.wpa_ie_len) { + if (!param->u.wpa_associate.wpa_ie) + return -EINVAL; + if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE)) + return -EINVAL; + if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) + return -EFAULT; + } if (param->u.wpa_associate.mode == 1) pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 7e594449..9eed5b5 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -91,12 +91,12 @@ config USB_DYNAMIC_MINORS If you are unsure about this, say N here. config USB_SUSPEND - bool "USB runtime power management (suspend/resume and wakeup)" + bool "USB runtime power management (autosuspend) and wakeup" depends on USB && PM_RUNTIME help If you say Y here, you can use driver calls or the sysfs - "power/level" file to suspend or resume individual USB - peripherals and to enable or disable autosuspend (see + "power/control" file to enable or disable autosuspend for + individual USB peripherals (see Documentation/usb/power-management.txt for more details). Also, USB "remote wakeup" signaling is supported, whereby some diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index f06f5db..1e6ccef 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -159,9 +159,9 @@ void usb_major_cleanup(void) int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { - int retval = -EINVAL; + int retval; int minor_base = class_driver->minor_base; - int minor = 0; + int minor; char name[20]; char *temp; @@ -173,12 +173,17 @@ int usb_register_dev(struct usb_interface *intf, */ minor_base = 0; #endif - intf->minor = -1; - - dbg ("looking for a minor, starting at %d", minor_base); if (class_driver->fops == NULL) - goto exit; + return -EINVAL; + if (intf->minor >= 0) + return -EADDRINUSE; + + retval = init_usb_class(); + if (retval) + return retval; + + dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base); down_write(&minor_rwsem); for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { @@ -186,20 +191,12 @@ int usb_register_dev(struct usb_interface *intf, continue; usb_minors[minor] = class_driver->fops; - - retval = 0; + intf->minor = minor; break; } up_write(&minor_rwsem); - - if (retval) - goto exit; - - retval = init_usb_class(); - if (retval) - goto exit; - - intf->minor = minor; + if (intf->minor < 0) + return -EXFULL; /* create a usb class device for this usb interface */ snprintf(name, sizeof(name), class_driver->name, minor - minor_base); @@ -213,11 +210,11 @@ int usb_register_dev(struct usb_interface *intf, "%s", temp); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); - usb_minors[intf->minor] = NULL; + usb_minors[minor] = NULL; + intf->minor = -1; up_write(&minor_rwsem); retval = PTR_ERR(intf->usb_dev); } -exit: return retval; } EXPORT_SYMBOL_GPL(usb_register_dev); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 844683e..9f0ce7d 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1802,6 +1802,7 @@ free_interfaces: intf->dev.groups = usb_interface_groups; intf->dev.dma_mask = dev->dev.dma_mask; INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); + intf->minor = -1; device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum, dev->devpath, diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 58b72d7..a1e8d27 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -119,6 +119,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci->broken_periodic = 1; ehci_info(ehci, "using broken periodic workaround\n"); } + if (pdev->device == 0x0806 || pdev->device == 0x0811 + || pdev->device == 0x0829) { + ehci_info(ehci, "disable lpm for langwell/penwell\n"); + ehci->has_lpm = 0; + } break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 4181638..afef7b0 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <mach/ohci.h> +#include <mach/pxa3xx-u2d.h> /* * UHC: USB Host Controller (OHCI-like) register definitions @@ -235,6 +236,9 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev) if (retval < 0) return retval; + if (cpu_is_pxa3xx()) + pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self); + uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE; __raw_writel(uhchr, ohci->mmio_base + UHCHR); __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE); @@ -251,6 +255,9 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev) inf = dev->platform_data; + if (cpu_is_pxa3xx()) + pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self); + if (inf->exit) inf->exit(dev); diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 59dc3d3..5ab5bb8 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -322,6 +322,7 @@ cppi_channel_allocate(struct dma_controller *c, index, transmit ? 'T' : 'R', cppi_ch); cppi_ch->hw_ep = ep; cppi_ch->channel.status = MUSB_DMA_STATUS_FREE; + cppi_ch->channel.max_len = 0x7fffffff; DBG(4, "Allocate CPPI%d %cX\n", index, transmit ? 'T' : 'R'); return &cppi_ch->channel; diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index c79a5e3..9e8639d 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -195,15 +195,14 @@ static const struct file_operations musb_regdump_fops = { static int musb_test_mode_open(struct inode *inode, struct file *file) { - file->private_data = inode->i_private; - return single_open(file, musb_test_mode_show, inode->i_private); } static ssize_t musb_test_mode_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { - struct musb *musb = file->private_data; + struct seq_file *s = file->private_data; + struct musb *musb = s->private; u8 test = 0; char buf[18]; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6fca870..d065e23 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -300,6 +300,11 @@ static void txstate(struct musb *musb, struct musb_request *req) #ifndef CONFIG_MUSB_PIO_ONLY if (is_dma_capable() && musb_ep->dma) { struct dma_controller *c = musb->dma_controller; + size_t request_size; + + /* setup DMA, then program endpoint CSR */ + request_size = min_t(size_t, request->length - request->actual, + musb_ep->dma->max_len); use_dma = (request->dma != DMA_ADDR_INVALID); @@ -307,11 +312,6 @@ static void txstate(struct musb *musb, struct musb_request *req) #ifdef CONFIG_USB_INVENTRA_DMA { - size_t request_size; - - /* setup DMA, then program endpoint CSR */ - request_size = min_t(size_t, request->length, - musb_ep->dma->max_len); if (request_size < musb_ep->packet_sz) musb_ep->dma->desired_mode = 0; else @@ -373,8 +373,8 @@ static void txstate(struct musb *musb, struct musb_request *req) use_dma = use_dma && c->channel_program( musb_ep->dma, musb_ep->packet_sz, 0, - request->dma, - request->length); + request->dma + request->actual, + request_size); if (!use_dma) { c->channel_release(musb_ep->dma); musb_ep->dma = NULL; @@ -386,8 +386,8 @@ static void txstate(struct musb *musb, struct musb_request *req) use_dma = use_dma && c->channel_program( musb_ep->dma, musb_ep->packet_sz, request->zero, - request->dma, - request->length); + request->dma + request->actual, + request_size); #endif } #endif @@ -501,26 +501,14 @@ void musb_g_tx(struct musb *musb, u8 epnum) request->zero = 0; } - /* ... or if not, then complete it. */ - musb_g_giveback(musb_ep, request, 0); - - /* - * Kickstart next transfer if appropriate; - * the packet that just completed might not - * be transmitted for hours or days. - * REVISIT for double buffering... - * FIXME revisit for stalls too... - */ - musb_ep_select(mbase, epnum); - csr = musb_readw(epio, MUSB_TXCSR); - if (csr & MUSB_TXCSR_FIFONOTEMPTY) - return; - - request = musb_ep->desc ? next_request(musb_ep) : NULL; - if (!request) { - DBG(4, "%s idle now\n", - musb_ep->end_point.name); - return; + if (request->actual == request->length) { + musb_g_giveback(musb_ep, request, 0); + request = musb_ep->desc ? next_request(musb_ep) : NULL; + if (!request) { + DBG(4, "%s idle now\n", + musb_ep->end_point.name); + return; + } } } @@ -568,11 +556,19 @@ static void rxstate(struct musb *musb, struct musb_request *req) { const u8 epnum = req->epnum; struct usb_request *request = &req->request; - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; + struct musb_ep *musb_ep; void __iomem *epio = musb->endpoints[epnum].regs; unsigned fifo_count = 0; - u16 len = musb_ep->packet_sz; + u16 len; u16 csr = musb_readw(epio, MUSB_RXCSR); + struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; + + if (hw_ep->is_shared_fifo) + musb_ep = &hw_ep->ep_in; + else + musb_ep = &hw_ep->ep_out; + + len = musb_ep->packet_sz; /* We shouldn't get here while DMA is active, but we do... */ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { @@ -647,8 +643,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) */ csr |= MUSB_RXCSR_DMAENAB; -#ifdef USE_MODE1 csr |= MUSB_RXCSR_AUTOCLEAR; +#ifdef USE_MODE1 /* csr |= MUSB_RXCSR_DMAMODE; */ /* this special sequence (enabling and then @@ -663,10 +659,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (request->actual < request->length) { int transfer_size = 0; #ifdef USE_MODE1 - transfer_size = min(request->length, + transfer_size = min(request->length - request->actual, channel->max_len); #else - transfer_size = len; + transfer_size = min(request->length - request->actual, + (unsigned)len); #endif if (transfer_size <= musb_ep->packet_sz) musb_ep->dma->desired_mode = 0; @@ -740,9 +737,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) u16 csr; struct usb_request *request; void __iomem *mbase = musb->mregs; - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; + struct musb_ep *musb_ep; void __iomem *epio = musb->endpoints[epnum].regs; struct dma_channel *dma; + struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; + + if (hw_ep->is_shared_fifo) + musb_ep = &hw_ep->ep_in; + else + musb_ep = &hw_ep->ep_out; musb_ep_select(mbase, epnum); @@ -1081,7 +1084,7 @@ struct free_record { /* * Context: controller locked, IRQs blocked. */ -static void musb_ep_restart(struct musb *musb, struct musb_request *req) +void musb_ep_restart(struct musb *musb, struct musb_request *req) { DBG(3, "<== %s request %p len %u on hw_ep%d\n", req->tx ? "TX/IN" : "RX/OUT", diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index c8b1403..572b1da 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -105,4 +105,6 @@ extern void musb_gadget_cleanup(struct musb *); extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); +extern void musb_ep_restart(struct musb *, struct musb_request *); + #endif /* __MUSB_GADGET_H */ diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 59bef8f..6dd03f4 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -261,6 +261,7 @@ __acquires(musb->lock) ctrlrequest->wIndex & 0x0f; struct musb_ep *musb_ep; struct musb_hw_ep *ep; + struct musb_request *request; void __iomem *regs; int is_in; u16 csr; @@ -302,6 +303,14 @@ __acquires(musb->lock) musb_writew(regs, MUSB_RXCSR, csr); } + /* Maybe start the first request in the queue */ + request = to_musb_request( + next_request(musb_ep)); + if (!musb_ep->busy && request) { + DBG(3, "restarting the request\n"); + musb_ep_restart(musb, request); + } + /* select ep0 again */ musb_ep_select(mbase, 0); } break; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 877d20b..9e65c47 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -660,6 +660,12 @@ static bool musb_tx_dma_program(struct dma_controller *dma, qh->segsize = length; + /* + * Ensure the data reaches to main memory before starting + * DMA transfer + */ + wmb(); + if (!dma->channel_program(channel, pkt_size, mode, urb->transfer_dma + offset, length)) { dma->channel_release(channel); diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 05aaac1..0bc9769 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -347,11 +347,20 @@ static void twl4030_i2c_access(struct twl4030_usb *twl, int on) } } -static void twl4030_phy_power(struct twl4030_usb *twl, int on) +static void __twl4030_phy_power(struct twl4030_usb *twl, int on) { - u8 pwr; + u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); + + if (on) + pwr &= ~PHY_PWR_PHYPWD; + else + pwr |= PHY_PWR_PHYPWD; - pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); + WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); +} + +static void twl4030_phy_power(struct twl4030_usb *twl, int on) +{ if (on) { regulator_enable(twl->usb3v1); regulator_enable(twl->usb1v8); @@ -365,15 +374,13 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); regulator_enable(twl->usb1v5); - pwr &= ~PHY_PWR_PHYPWD; - WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + __twl4030_phy_power(twl, 1); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); - } else { - pwr |= PHY_PWR_PHYPWD; - WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + } else { + __twl4030_phy_power(twl, 0); regulator_disable(twl->usb1v5); regulator_disable(twl->usb1v8); regulator_disable(twl->usb3v1); @@ -387,19 +394,25 @@ static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off) twl4030_phy_power(twl, 0); twl->asleep = 1; + dev_dbg(twl->dev, "%s\n", __func__); } -static void twl4030_phy_resume(struct twl4030_usb *twl) +static void __twl4030_phy_resume(struct twl4030_usb *twl) { - if (!twl->asleep) - return; - twl4030_phy_power(twl, 1); twl4030_i2c_access(twl, 1); twl4030_usb_set_mode(twl, twl->usb_mode); if (twl->usb_mode == T2_USB_MODE_ULPI) twl4030_i2c_access(twl, 0); +} + +static void twl4030_phy_resume(struct twl4030_usb *twl) +{ + if (!twl->asleep) + return; + __twl4030_phy_resume(twl); twl->asleep = 0; + dev_dbg(twl->dev, "%s\n", __func__); } static int twl4030_usb_ldo_init(struct twl4030_usb *twl) @@ -408,8 +421,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); - /* put VUSB3V1 LDO in active state */ - twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); + /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ + /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ /* input to VUSB3V1 LDO is from VBAT, not VBUS */ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); @@ -502,6 +515,26 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) return IRQ_HANDLED; } +static void twl4030_usb_phy_init(struct twl4030_usb *twl) +{ + int status; + + status = twl4030_usb_linkstat(twl); + if (status >= 0) { + if (status == USB_EVENT_NONE) { + __twl4030_phy_power(twl, 0); + twl->asleep = 1; + } else { + __twl4030_phy_resume(twl); + twl->asleep = 0; + } + + blocking_notifier_call_chain(&twl->otg.notifier, status, + twl->otg.gadget); + } + sysfs_notify(&twl->dev->kobj, NULL, "vbus"); +} + static int twl4030_set_suspend(struct otg_transceiver *x, int suspend) { struct twl4030_usb *twl = xceiv_to_twl(x); @@ -550,7 +583,6 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) struct twl4030_usb_data *pdata = pdev->dev.platform_data; struct twl4030_usb *twl; int status, err; - u8 pwr; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); @@ -569,10 +601,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) twl->otg.set_peripheral = twl4030_set_peripheral; twl->otg.set_suspend = twl4030_set_suspend; twl->usb_mode = pdata->usb_mode; - - pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); - - twl->asleep = (pwr & PHY_PWR_PHYPWD); + twl->asleep = 1; /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -610,15 +639,10 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) return status; } - /* The IRQ handler just handles changes from the previous states - * of the ID and VBUS pins ... in probe() we must initialize that - * previous state. The easy way: fake an IRQ. - * - * REVISIT: a real IRQ might have happened already, if PREEMPT is - * enabled. Else the IRQ may not yet be configured or enabled, - * because of scheduling delays. + /* Power down phy or make it work according to + * current link state. */ - twl4030_usb_irq(twl->irq, twl); + twl4030_usb_phy_init(twl); dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); return 0; diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 30922a7..aa66581 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -2024,6 +2024,9 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file, case TIOCGICOUNT: cnow = mos7720_port->icount; + + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + icount.cts = cnow.cts; icount.dsr = cnow.dsr; icount.rng = cnow.rng; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 1c9b6e9..1a42bc2 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2285,6 +2285,9 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file, case TIOCGICOUNT: cnow = mos7840_port->icount; smp_rmb(); + + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + icount.cts = cnow.cts; icount.dsr = cnow.dsr; icount.rng = cnow.rng; diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 29e850a..7c80082 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -243,7 +243,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, int r, nlogs = 0; while (datalen > 0) { - if (unlikely(headcount >= VHOST_NET_MAX_SG)) { + if (unlikely(seg >= VHOST_NET_MAX_SG)) { r = -ENOBUFS; goto err; } diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c579dcc..dd3d6f7 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -858,11 +858,12 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, if (r < 0) return r; len -= l; - if (!len) + if (!len) { + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); return 0; + } } - if (vq->log_ctx) - eventfd_signal(vq->log_ctx, 1); /* Length written exceeds what we have stored. This is a bug. */ BUG(); return 0; diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 84f8423..7ccc967 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -3508,7 +3508,7 @@ static void fbcon_exit(void) softback_buf = 0UL; for (i = 0; i < FB_MAX; i++) { - int pending; + int pending = 0; mapped = 0; info = registered_fb[i]; @@ -3516,7 +3516,8 @@ static void fbcon_exit(void) if (info == NULL) continue; - pending = cancel_work_sync(&info->queue); + if (info->queue.func) + pending = cancel_work_sync(&info->queue); DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" : "no")); diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 815f84b..70477c2 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -13,7 +13,7 @@ #include <linux/platform_device.h> #include <linux/screen_info.h> #include <linux/dmi.h> - +#include <linux/pci.h> #include <video/vga.h> static struct fb_var_screeninfo efifb_defined __devinitdata = { @@ -39,17 +39,31 @@ enum { M_I20, /* 20-Inch iMac */ M_I20_SR, /* 20-Inch iMac (Santa Rosa) */ M_I24, /* 24-Inch iMac */ + M_I24_8_1, /* 24-Inch iMac, 8,1th gen */ + M_I24_10_1, /* 24-Inch iMac, 10,1th gen */ + M_I27_11_1, /* 27-Inch iMac, 11,1th gen */ M_MINI, /* Mac Mini */ + M_MINI_3_1, /* Mac Mini, 3,1th gen */ + M_MINI_4_1, /* Mac Mini, 4,1th gen */ M_MB, /* MacBook */ M_MB_2, /* MacBook, 2nd rev. */ M_MB_3, /* MacBook, 3rd rev. */ + M_MB_5_1, /* MacBook, 5th rev. */ + M_MB_6_1, /* MacBook, 6th rev. */ + M_MB_7_1, /* MacBook, 7th rev. */ M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ M_MBA, /* MacBook Air */ M_MBP, /* MacBook Pro */ M_MBP_2, /* MacBook Pro 2nd gen */ + M_MBP_2_2, /* MacBook Pro 2,2nd gen */ M_MBP_SR, /* MacBook Pro (Santa Rosa) */ M_MBP_4, /* MacBook Pro, 4th gen */ M_MBP_5_1, /* MacBook Pro, 5,1th gen */ + M_MBP_5_2, /* MacBook Pro, 5,2th gen */ + M_MBP_5_3, /* MacBook Pro, 5,3rd gen */ + M_MBP_6_1, /* MacBook Pro, 6,1th gen */ + M_MBP_6_2, /* MacBook Pro, 6,2th gen */ + M_MBP_7_1, /* MacBook Pro, 7,1th gen */ M_UNKNOWN /* placeholder */ }; @@ -64,14 +78,28 @@ static struct efifb_dmi_info { [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ + [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, + [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, + [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, + [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, + [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, + [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, + [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, + [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ + [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, + [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, + [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, + [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, + [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, + [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } }; @@ -92,7 +120,12 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB), /* At least one of these two will be right; maybe both? */ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB), @@ -101,14 +134,23 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1), {}, }; @@ -116,7 +158,7 @@ static int set_system(const struct dmi_system_id *id) { struct efifb_dmi_info *info = id->driver_data; if (info->base == 0) - return -ENODEV; + return 0; printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " "(%dx%d, stride %d)\n", id->ident, @@ -124,18 +166,55 @@ static int set_system(const struct dmi_system_id *id) info->stride); /* Trust the bootloader over the DMI tables */ - if (screen_info.lfb_base == 0) + if (screen_info.lfb_base == 0) { +#if defined(CONFIG_PCI) + struct pci_dev *dev = NULL; + int found_bar = 0; +#endif screen_info.lfb_base = info->base; - if (screen_info.lfb_linelength == 0) - screen_info.lfb_linelength = info->stride; - if (screen_info.lfb_width == 0) - screen_info.lfb_width = info->width; - if (screen_info.lfb_height == 0) - screen_info.lfb_height = info->height; - if (screen_info.orig_video_isVGA == 0) - screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; - return 0; +#if defined(CONFIG_PCI) + /* make sure that the address in the table is actually on a + * VGA device's PCI BAR */ + + for_each_pci_dev(dev) { + int i; + if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + continue; + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + resource_size_t start, end; + + start = pci_resource_start(dev, i); + if (start == 0) + break; + end = pci_resource_end(dev, i); + if (screen_info.lfb_base >= start && + screen_info.lfb_base < end) { + found_bar = 1; + } + } + } + if (!found_bar) + screen_info.lfb_base = 0; +#endif + } + if (screen_info.lfb_base) { + if (screen_info.lfb_linelength == 0) + screen_info.lfb_linelength = info->stride; + if (screen_info.lfb_width == 0) + screen_info.lfb_width = info->width; + if (screen_info.lfb_height == 0) + screen_info.lfb_height = info->height; + if (screen_info.orig_video_isVGA == 0) + screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; + } else { + screen_info.lfb_linelength = 0; + screen_info.lfb_width = 0; + screen_info.lfb_height = 0; + screen_info.orig_video_isVGA = 0; + return 0; + } + return 1; } static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c index 5d786bd..cea6403 100644 --- a/drivers/video/pxa168fb.c +++ b/drivers/video/pxa168fb.c @@ -298,8 +298,8 @@ static void set_dma_control0(struct pxa168fb_info *fbi) * Set bit to enable graphics DMA. */ x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); - x |= fbi->active ? 0x00000100 : 0; - fbi->active = 0; + x &= ~CFG_GRA_ENA_MASK; + x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0); /* * If we are in a pseudo-color mode, we need to enable @@ -784,12 +784,53 @@ failed: return ret; } +static int __devexit pxa168fb_remove(struct platform_device *pdev) +{ + struct pxa168fb_info *fbi = platform_get_drvdata(pdev); + struct fb_info *info; + int irq; + unsigned int data; + + if (!fbi) + return 0; + + /* disable DMA transfer */ + data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); + data &= ~CFG_GRA_ENA_MASK; + writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0); + + info = fbi->info; + + unregister_framebuffer(info); + + writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA); + + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + + irq = platform_get_irq(pdev, 0); + free_irq(irq, fbi); + + dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), + info->screen_base, info->fix.smem_start); + + iounmap(fbi->reg_base); + + clk_disable(fbi->clk); + clk_put(fbi->clk); + + framebuffer_release(info); + + return 0; +} + static struct platform_driver pxa168fb_driver = { .driver = { .name = "pxa168-fb", .owner = THIS_MODULE, }, .probe = pxa168fb_probe, + .remove = __devexit_p(pxa168fb_remove), }; static int __init pxa168fb_init(void) @@ -798,6 +839,12 @@ static int __init pxa168fb_init(void) } module_init(pxa168fb_init); +static void __exit pxa168fb_exit(void) +{ + platform_driver_unregister(&pxa168fb_driver); +} +module_exit(pxa168fb_exit); + MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " "Green Wan <gwan@marvell.com>"); MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 559bf17..b52f8e4 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1701,6 +1701,9 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, break; case FBIOGET_VBLANK: + + memset(&sisvbblank, 0, sizeof(struct fb_vblank)); + sisvbblank.count = 0; sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c index da03c07..4d553d0 100644 --- a/drivers/video/via/ioctl.c +++ b/drivers/video/via/ioctl.c @@ -25,6 +25,8 @@ int viafb_ioctl_get_viafb_info(u_long arg) { struct viafb_ioctl_info viainfo; + memset(&viainfo, 0, sizeof(struct viafb_ioctl_info)); + viainfo.viafb_id = VIAID; viainfo.vendor_id = PCI_VIA_VENDOR_ID; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b036677..24efd8e 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -213,11 +213,11 @@ config OMAP_WATCHDOG here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. config PNX4008_WATCHDOG - tristate "PNX4008 Watchdog" - depends on ARCH_PNX4008 + tristate "PNX4008 and LPC32XX Watchdog" + depends on ARCH_PNX4008 || ARCH_LPC32XX help Say Y here if to include support for the watchdog timer - in the PNX4008 processor. + in the PNX4008 or LPC32XX processor. This driver can be built as a module by choosing M. The module will be called pnx4008_wdt. diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 88c83aa..f31493e 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -305,7 +305,7 @@ static int __init sbwdog_init(void) if (ret) { printk(KERN_ERR "%s: failed to request irq 1 - %d\n", ident.identity, ret); - return ret; + goto out; } ret = misc_register(&sbwdog_miscdev); @@ -313,14 +313,20 @@ static int __init sbwdog_init(void) printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", ident.identity, timeout / 1000000, (timeout / 100000) % 10); - } else - free_irq(1, (void *)user_dog); + return 0; + } + free_irq(1, (void *)user_dog); +out: + unregister_reboot_notifier(&sbwdog_notifier); + return ret; } static void __exit sbwdog_exit(void) { misc_deregister(&sbwdog_miscdev); + free_irq(1, (void *)user_dog); + unregister_reboot_notifier(&sbwdog_notifier); } module_init(sbwdog_init); diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 458c499..18cdeb4 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -449,6 +449,9 @@ static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) wdt->pdev = pdev; mutex_init(&wdt->lock); + /* make sure that the watchdog is disabled */ + ts72xx_wdt_stop(wdt); + error = misc_register(&ts72xx_wdt_miscdev); if (error) { dev_err(&pdev->dev, "failed to register miscdev\n"); diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 29bac51..d409495 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -755,7 +755,10 @@ int register_xenstore_notifier(struct notifier_block *nb) { int ret = 0; - blocking_notifier_chain_register(&xenstore_chain, nb); + if (xenstored_ready > 0) + ret = nb->notifier_call(nb, 0, NULL); + else + blocking_notifier_chain_register(&xenstore_chain, nb); return ret; } @@ -769,7 +772,7 @@ EXPORT_SYMBOL_GPL(unregister_xenstore_notifier); void xenbus_probe(struct work_struct *unused) { - BUG_ON((xenstored_ready <= 0)); + xenstored_ready = 1; /* Enumerate devices in xenstore and watch for changes. */ xenbus_probe_devices(&xenbus_frontend); @@ -835,8 +838,8 @@ static int __init xenbus_init(void) xen_store_evtchn = xen_start_info->store_evtchn; xen_store_mfn = xen_start_info->store_mfn; xen_store_interface = mfn_to_virt(xen_store_mfn); + xenstored_ready = 1; } - xenstored_ready = 1; } /* Initialize the interface to xenstore. */ diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 16c8a2a..899f168 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -292,9 +292,11 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) fid = filp->private_data; P9_DPRINTK(P9_DEBUG_VFS, - "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); + "v9fs_dir_release: inode: %p filp: %p fid: %d\n", + inode, filp, fid ? fid->fid : -1); filemap_write_and_wait(inode->i_mapping); - p9_client_clunk(fid); + if (fid) + p9_client_clunk(fid); return 0; } diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c7c23ea..9e670d5 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -730,7 +730,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); goto error; } - dentry->d_op = &v9fs_cached_dentry_operations; + if (v9ses->cache) + dentry->d_op = &v9fs_cached_dentry_operations; + else + dentry->d_op = &v9fs_dentry_operations; d_instantiate(dentry, inode); err = v9fs_fid_add(dentry, fid); if (err < 0) @@ -1128,6 +1131,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); generic_fillattr(dentry->d_inode, stat); + p9stat_free(st); kfree(st); return 0; } @@ -1489,6 +1493,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) retval = strnlen(buffer, buflen); done: + p9stat_free(st); kfree(st); return retval; } @@ -1942,7 +1947,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { .unlink = v9fs_vfs_unlink, .mkdir = v9fs_vfs_mkdir, .rmdir = v9fs_vfs_rmdir, - .mknod = v9fs_vfs_mknod_dotl, + .mknod = v9fs_vfs_mknod, .rename = v9fs_vfs_rename, .getattr = v9fs_vfs_getattr, .setattr = v9fs_vfs_setattr, diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index f931107..1d12ba0 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -122,6 +122,10 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, fid = v9fs_session_init(v9ses, dev_name, data); if (IS_ERR(fid)) { retval = PTR_ERR(fid); + /* + * we need to call session_close to tear down some + * of the data structure setup by session_init + */ goto close_session; } @@ -144,7 +148,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, retval = -ENOMEM; goto release_sb; } - sb->s_root = root; if (v9fs_proto_dotl(v9ses)) { @@ -152,7 +155,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); if (IS_ERR(st)) { retval = PTR_ERR(st); - goto clunk_fid; + goto release_sb; } v9fs_stat2inode_dotl(st, root->d_inode); @@ -162,7 +165,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, st = p9_client_stat(fid); if (IS_ERR(st)) { retval = PTR_ERR(st); - goto clunk_fid; + goto release_sb; } root->d_inode->i_ino = v9fs_qid2ino(&st->qid); @@ -174,19 +177,24 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, v9fs_fid_add(root, fid); -P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); + P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); simple_set_mnt(mnt, sb); return 0; clunk_fid: p9_client_clunk(fid); - close_session: v9fs_session_close(v9ses); kfree(v9ses); return retval; - release_sb: + /* + * we will do the session_close and root dentry release + * in the below call. But we need to clunk fid, because we haven't + * attached the fid to dentry so it won't get clunked + * automatically. + */ + p9_client_clunk(fid); deactivate_locked_super(sb); return retval; } @@ -712,8 +712,16 @@ static ssize_t aio_run_iocb(struct kiocb *iocb) */ ret = retry(iocb); - if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) + if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) { + /* + * There's no easy way to restart the syscall since other AIO's + * may be already running. Just fail this IO with EINTR. + */ + if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR || + ret == -ERESTARTNOHAND || ret == -ERESTART_RESTARTBLOCK)) + ret = -EINTR; aio_complete(iocb, ret, 0); + } out: spin_lock_irq(&ctx->ctx_lock); @@ -1659,6 +1667,9 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (unlikely(nr < 0)) return -EINVAL; + if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) + nr = LONG_MAX/sizeof(*iocbpp); + if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) return -EFAULT; diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index f96eff0..a6395bd 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -134,10 +134,6 @@ static int aout_core_dump(struct coredump_params *cprm) if (!dump_write(file, dump_start, dump_size)) goto end_coredump; } -/* Finally dump the task struct. Not be used by gdb, but could be useful */ - set_fs(KERNEL_DS); - if (!dump_write(file, current, sizeof(*current))) - goto end_coredump; end_coredump: set_fs(fs); return has_dumped; diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig index bc87b9c..0fcd264 100644 --- a/fs/ceph/Kconfig +++ b/fs/ceph/Kconfig @@ -3,6 +3,7 @@ config CEPH_FS depends on INET && EXPERIMENTAL select LIBCRC32C select CRYPTO_AES + select CRYPTO help Choose Y or M here to include support for mounting the experimental Ceph distributed file system. Ceph is an extremely diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 4cfce1e..efbc604 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -411,8 +411,8 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) if (i_size < page_off + len) len = i_size - page_off; - dout("writepage %p page %p index %lu on %llu~%u\n", - inode, page, page->index, page_off, len); + dout("writepage %p page %p index %lu on %llu~%u snapc %p\n", + inode, page, page->index, page_off, len, snapc); writeback_stat = atomic_long_inc_return(&client->writeback_count); if (writeback_stat > @@ -766,7 +766,8 @@ get_more_pages: /* ok */ if (locked_pages == 0) { /* prepare async write request */ - offset = page->index << PAGE_CACHE_SHIFT; + offset = (unsigned long long)page->index + << PAGE_CACHE_SHIFT; len = wsize; req = ceph_osdc_new_request(&client->osdc, &ci->i_layout, diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index a2069b6..5e9da99 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -814,7 +814,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci) used |= CEPH_CAP_PIN; if (ci->i_rd_ref) used |= CEPH_CAP_FILE_RD; - if (ci->i_rdcache_ref || ci->i_rdcache_gen) + if (ci->i_rdcache_ref || ci->vfs_inode.i_data.nrpages) used |= CEPH_CAP_FILE_CACHE; if (ci->i_wr_ref) used |= CEPH_CAP_FILE_WR; @@ -1195,10 +1195,14 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, * asynchronously back to the MDS once sync writes complete and dirty * data is written out. * + * Unless @again is true, skip cap_snaps that were already sent to + * the MDS (i.e., during this session). + * * Called under i_lock. Takes s_mutex as needed. */ void __ceph_flush_snaps(struct ceph_inode_info *ci, - struct ceph_mds_session **psession) + struct ceph_mds_session **psession, + int again) __releases(ci->vfs_inode->i_lock) __acquires(ci->vfs_inode->i_lock) { @@ -1227,7 +1231,7 @@ retry: * pages to be written out. */ if (capsnap->dirty_pages || capsnap->writing) - continue; + break; /* * if cap writeback already occurred, we should have dropped @@ -1240,6 +1244,13 @@ retry: dout("no auth cap (migrating?), doing nothing\n"); goto out; } + + /* only flush each capsnap once */ + if (!again && !list_empty(&capsnap->flushing_item)) { + dout("already flushed %p, skipping\n", capsnap); + continue; + } + mds = ci->i_auth_cap->session->s_mds; mseq = ci->i_auth_cap->mseq; @@ -1276,8 +1287,8 @@ retry: &session->s_cap_snaps_flushing); spin_unlock(&inode->i_lock); - dout("flush_snaps %p cap_snap %p follows %lld size %llu\n", - inode, capsnap, next_follows, capsnap->size); + dout("flush_snaps %p cap_snap %p follows %lld tid %llu\n", + inode, capsnap, capsnap->follows, capsnap->flush_tid); send_cap_msg(session, ceph_vino(inode).ino, 0, CEPH_CAP_OP_FLUSHSNAP, capsnap->issued, 0, capsnap->dirty, 0, capsnap->flush_tid, 0, mseq, @@ -1314,7 +1325,7 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) struct inode *inode = &ci->vfs_inode; spin_lock(&inode->i_lock); - __ceph_flush_snaps(ci, NULL); + __ceph_flush_snaps(ci, NULL, 0); spin_unlock(&inode->i_lock); } @@ -1477,7 +1488,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, /* flush snaps first time around only */ if (!list_empty(&ci->i_cap_snaps)) - __ceph_flush_snaps(ci, &session); + __ceph_flush_snaps(ci, &session, 0); goto retry_locked; retry: spin_lock(&inode->i_lock); @@ -1894,7 +1905,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc, if (cap && cap->session == session) { dout("kick_flushing_caps %p cap %p capsnap %p\n", inode, cap, capsnap); - __ceph_flush_snaps(ci, &session); + __ceph_flush_snaps(ci, &session, 1); } else { pr_err("%p auth cap %p not mds%d ???\n", inode, cap, session->s_mds); @@ -2272,7 +2283,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, { struct ceph_inode_info *ci = ceph_inode(inode); int mds = session->s_mds; - int seq = le32_to_cpu(grant->seq); + unsigned seq = le32_to_cpu(grant->seq); + unsigned issue_seq = le32_to_cpu(grant->issue_seq); int newcaps = le32_to_cpu(grant->caps); int issued, implemented, used, wanted, dirty; u64 size = le64_to_cpu(grant->size); @@ -2284,8 +2296,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, int revoked_rdcache = 0; int queue_invalidate = 0; - dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", - inode, cap, mds, seq, ceph_cap_string(newcaps)); + dout("handle_cap_grant inode %p cap %p mds%d seq %u/%u %s\n", + inode, cap, mds, seq, issue_seq, ceph_cap_string(newcaps)); dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, inode->i_size); @@ -2381,6 +2393,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, } cap->seq = seq; + cap->issue_seq = issue_seq; /* file layout may have changed */ ci->i_layout = grant->layout; @@ -2763,15 +2776,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, if (op == CEPH_CAP_OP_IMPORT) __queue_cap_release(session, vino.ino, cap_id, mseq, seq); - - /* - * send any full release message to try to move things - * along for the mds (who clearly thinks we still have this - * cap). - */ - ceph_add_cap_releases(mdsc, session); - ceph_send_cap_releases(mdsc, session); - goto done; + goto flush_cap_releases; } /* these will work even if we don't have a cap yet */ @@ -2799,7 +2804,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, dout(" no cap on %p ino %llx.%llx from mds%d\n", inode, ceph_ino(inode), ceph_snap(inode), mds); spin_unlock(&inode->i_lock); - goto done; + goto flush_cap_releases; } /* note that each of these drops i_lock for us */ @@ -2823,6 +2828,17 @@ void ceph_handle_caps(struct ceph_mds_session *session, ceph_cap_op_name(op)); } + goto done; + +flush_cap_releases: + /* + * send any full release message to try to move things + * along for the mds (who clearly thinks we still have this + * cap). + */ + ceph_add_cap_releases(mdsc, session); + ceph_send_cap_releases(mdsc, session); + done: mutex_unlock(&session->s_mutex); done_unlocked: diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 6e4f43f..a1986eb 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1021,11 +1021,15 @@ out_touch: static void ceph_dentry_release(struct dentry *dentry) { struct ceph_dentry_info *di = ceph_dentry(dentry); - struct inode *parent_inode = dentry->d_parent->d_inode; - u64 snapid = ceph_snap(parent_inode); + struct inode *parent_inode = NULL; + u64 snapid = CEPH_NOSNAP; + if (!IS_ROOT(dentry)) { + parent_inode = dentry->d_parent->d_inode; + if (parent_inode) + snapid = ceph_snap(parent_inode); + } dout("dentry_release %p parent %p\n", dentry, parent_inode); - if (parent_inode && snapid != CEPH_SNAPDIR) { struct ceph_inode_info *ci = ceph_inode(parent_inode); diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 4480cb1..e38423e 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -42,32 +42,37 @@ struct ceph_nfs_confh { static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, int connectable) { + int type; struct ceph_nfs_fh *fh = (void *)rawfh; struct ceph_nfs_confh *cfh = (void *)rawfh; struct dentry *parent = dentry->d_parent; struct inode *inode = dentry->d_inode; - int type; + int connected_handle_length = sizeof(*cfh)/4; + int handle_length = sizeof(*fh)/4; /* don't re-export snaps */ if (ceph_snap(inode) != CEPH_NOSNAP) return -EINVAL; - if (*max_len >= sizeof(*cfh)) { + if (*max_len >= connected_handle_length) { dout("encode_fh %p connectable\n", dentry); cfh->ino = ceph_ino(dentry->d_inode); cfh->parent_ino = ceph_ino(parent->d_inode); cfh->parent_name_hash = parent->d_name.hash; - *max_len = sizeof(*cfh); + *max_len = connected_handle_length; type = 2; - } else if (*max_len > sizeof(*fh)) { - if (connectable) - return -ENOSPC; + } else if (*max_len >= handle_length) { + if (connectable) { + *max_len = connected_handle_length; + return 255; + } dout("encode_fh %p\n", dentry); fh->ino = ceph_ino(dentry->d_inode); - *max_len = sizeof(*fh); + *max_len = handle_length; type = 1; } else { - return -ENOSPC; + *max_len = handle_length; + return 255; } return type; } diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 8c044a4..66e4da6 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -697,7 +697,7 @@ more: * start_request so that a tid has been assigned. */ spin_lock(&ci->i_unsafe_lock); - list_add(&ci->i_unsafe_writes, &req->r_unsafe_item); + list_add(&req->r_unsafe_item, &ci->i_unsafe_writes); spin_unlock(&ci->i_unsafe_lock); ceph_get_cap_refs(ci, CEPH_CAP_FILE_WR); } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index e7cca41..62377ec 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -845,7 +845,7 @@ static void ceph_set_dentry_offset(struct dentry *dn) * the caller) if we fail. */ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, - bool *prehash) + bool *prehash, bool set_offset) { struct dentry *realdn; @@ -877,7 +877,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, } if ((!prehash || *prehash) && d_unhashed(dn)) d_rehash(dn); - ceph_set_dentry_offset(dn); + if (set_offset) + ceph_set_dentry_offset(dn); out: return dn; } @@ -1062,7 +1063,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, d_delete(dn); goto done; } - dn = splice_dentry(dn, in, &have_lease); + dn = splice_dentry(dn, in, &have_lease, true); if (IS_ERR(dn)) { err = PTR_ERR(dn); goto done; @@ -1105,7 +1106,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, goto done; } dout(" linking snapped dir %p to dn %p\n", in, dn); - dn = splice_dentry(dn, in, NULL); + dn = splice_dentry(dn, in, NULL, true); if (IS_ERR(dn)) { err = PTR_ERR(dn); goto done; @@ -1237,7 +1238,7 @@ retry_lookup: err = PTR_ERR(in); goto out; } - dn = splice_dentry(dn, in, NULL); + dn = splice_dentry(dn, in, NULL, false); if (IS_ERR(dn)) dn = NULL; } diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index f091b13..fad95f8 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2374,6 +2374,8 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, num_fcntl_locks, num_flock_locks); unlock_kernel(); + } else { + err = ceph_pagelist_append(pagelist, &rec, reclen); } out_free: diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c index dfced1d..3b5571b 100644 --- a/fs/ceph/osd_client.c +++ b/fs/ceph/osd_client.c @@ -549,7 +549,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, */ static void __cancel_request(struct ceph_osd_request *req) { - if (req->r_sent) { + if (req->r_sent && req->r_osd) { ceph_con_revoke(&req->r_osd->o_con, req->r_request); req->r_sent = 0; } diff --git a/fs/ceph/pagelist.c b/fs/ceph/pagelist.c index b6859f4..46a368b 100644 --- a/fs/ceph/pagelist.c +++ b/fs/ceph/pagelist.c @@ -5,10 +5,18 @@ #include "pagelist.h" +static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl) +{ + struct page *page = list_entry(pl->head.prev, struct page, + lru); + kunmap(page); +} + int ceph_pagelist_release(struct ceph_pagelist *pl) { if (pl->mapped_tail) - kunmap(pl->mapped_tail); + ceph_pagelist_unmap_tail(pl); + while (!list_empty(&pl->head)) { struct page *page = list_first_entry(&pl->head, struct page, lru); @@ -26,7 +34,7 @@ static int ceph_pagelist_addpage(struct ceph_pagelist *pl) pl->room += PAGE_SIZE; list_add_tail(&page->lru, &pl->head); if (pl->mapped_tail) - kunmap(pl->mapped_tail); + ceph_pagelist_unmap_tail(pl); pl->mapped_tail = kmap(page); return 0; } diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 4868b9d..190b6c4 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -119,6 +119,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm( INIT_LIST_HEAD(&realm->children); INIT_LIST_HEAD(&realm->child_item); INIT_LIST_HEAD(&realm->empty_item); + INIT_LIST_HEAD(&realm->dirty_item); INIT_LIST_HEAD(&realm->inodes_with_caps); spin_lock_init(&realm->inodes_with_caps_lock); __insert_snap_realm(&mdsc->snap_realms, realm); @@ -467,7 +468,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) INIT_LIST_HEAD(&capsnap->ci_item); INIT_LIST_HEAD(&capsnap->flushing_item); - capsnap->follows = snapc->seq - 1; + capsnap->follows = snapc->seq; capsnap->issued = __ceph_caps_issued(ci, NULL); capsnap->dirty = dirty; @@ -604,6 +605,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc, struct ceph_snap_realm *realm; int invalidate = 0; int err = -ENOMEM; + LIST_HEAD(dirty_realms); dout("update_snap_trace deletion=%d\n", deletion); more: @@ -626,24 +628,6 @@ more: } } - if (le64_to_cpu(ri->seq) > realm->seq) { - dout("update_snap_trace updating %llx %p %lld -> %lld\n", - realm->ino, realm, realm->seq, le64_to_cpu(ri->seq)); - /* - * if the realm seq has changed, queue a cap_snap for every - * inode with open caps. we do this _before_ we update - * the realm info so that we prepare for writeback under the - * _previous_ snap context. - * - * ...unless it's a snap deletion! - */ - if (!deletion) - queue_realm_cap_snaps(realm); - } else { - dout("update_snap_trace %llx %p seq %lld unchanged\n", - realm->ino, realm, realm->seq); - } - /* ensure the parent is correct */ err = adjust_snap_realm_parent(mdsc, realm, le64_to_cpu(ri->parent)); if (err < 0) @@ -651,6 +635,8 @@ more: invalidate += err; if (le64_to_cpu(ri->seq) > realm->seq) { + dout("update_snap_trace updating %llx %p %lld -> %lld\n", + realm->ino, realm, realm->seq, le64_to_cpu(ri->seq)); /* update realm parameters, snap lists */ realm->seq = le64_to_cpu(ri->seq); realm->created = le64_to_cpu(ri->created); @@ -668,9 +654,17 @@ more: if (err < 0) goto fail; + /* queue realm for cap_snap creation */ + list_add(&realm->dirty_item, &dirty_realms); + invalidate = 1; } else if (!realm->cached_context) { + dout("update_snap_trace %llx %p seq %lld new\n", + realm->ino, realm, realm->seq); invalidate = 1; + } else { + dout("update_snap_trace %llx %p seq %lld unchanged\n", + realm->ino, realm, realm->seq); } dout("done with %llx %p, invalidated=%d, %p %p\n", realm->ino, @@ -683,6 +677,14 @@ more: if (invalidate) rebuild_snap_realms(realm); + /* + * queue cap snaps _after_ we've built the new snap contexts, + * so that i_head_snapc can be set appropriately. + */ + list_for_each_entry(realm, &dirty_realms, dirty_item) { + queue_realm_cap_snaps(realm); + } + __cleanup_empty_realms(mdsc); return 0; @@ -715,7 +717,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc) igrab(inode); spin_unlock(&mdsc->snap_flush_lock); spin_lock(&inode->i_lock); - __ceph_flush_snaps(ci, &session); + __ceph_flush_snaps(ci, &session, 0); spin_unlock(&inode->i_lock); iput(inode); spin_lock(&mdsc->snap_flush_lock); @@ -816,6 +818,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, }; struct inode *inode = ceph_find_inode(sb, vino); struct ceph_inode_info *ci; + struct ceph_snap_realm *oldrealm; if (!inode) continue; @@ -841,18 +844,19 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, dout(" will move %p to split realm %llx %p\n", inode, realm->ino, realm); /* - * Remove the inode from the realm's inode - * list, but don't add it to the new realm - * yet. We don't want the cap_snap to be - * queued (again) by ceph_update_snap_trace() - * below. Queue it _now_, under the old context. + * Move the inode to the new realm */ spin_lock(&realm->inodes_with_caps_lock); list_del_init(&ci->i_snap_realm_item); + list_add(&ci->i_snap_realm_item, + &realm->inodes_with_caps); + oldrealm = ci->i_snap_realm; + ci->i_snap_realm = realm; spin_unlock(&realm->inodes_with_caps_lock); spin_unlock(&inode->i_lock); - ceph_queue_cap_snap(ci); + ceph_get_snap_realm(mdsc, realm); + ceph_put_snap_realm(mdsc, oldrealm); iput(inode); continue; @@ -880,43 +884,9 @@ skip_inode: ceph_update_snap_trace(mdsc, p, e, op == CEPH_SNAP_OP_DESTROY); - if (op == CEPH_SNAP_OP_SPLIT) { - /* - * ok, _now_ add the inodes into the new realm. - */ - for (i = 0; i < num_split_inos; i++) { - struct ceph_vino vino = { - .ino = le64_to_cpu(split_inos[i]), - .snap = CEPH_NOSNAP, - }; - struct inode *inode = ceph_find_inode(sb, vino); - struct ceph_inode_info *ci; - - if (!inode) - continue; - ci = ceph_inode(inode); - spin_lock(&inode->i_lock); - if (list_empty(&ci->i_snap_realm_item)) { - struct ceph_snap_realm *oldrealm = - ci->i_snap_realm; - - dout(" moving %p to split realm %llx %p\n", - inode, realm->ino, realm); - spin_lock(&realm->inodes_with_caps_lock); - list_add(&ci->i_snap_realm_item, - &realm->inodes_with_caps); - ci->i_snap_realm = realm; - spin_unlock(&realm->inodes_with_caps_lock); - ceph_get_snap_realm(mdsc, realm); - ceph_put_snap_realm(mdsc, oldrealm); - } - spin_unlock(&inode->i_lock); - iput(inode); - } - + if (op == CEPH_SNAP_OP_SPLIT) /* we took a reference when we created the realm, above */ ceph_put_snap_realm(mdsc, realm); - } __cleanup_empty_realms(mdsc); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index c33897a..b87638e 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -690,6 +690,8 @@ struct ceph_snap_realm { struct list_head empty_item; /* if i have ref==0 */ + struct list_head dirty_item; /* if realm needs new context */ + /* the current set of snaps for this realm */ struct ceph_snap_context *cached_context; @@ -826,7 +828,8 @@ extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had); extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, struct ceph_snap_context *snapc); extern void __ceph_flush_snaps(struct ceph_inode_info *ci, - struct ceph_mds_session **psession); + struct ceph_mds_session **psession, + int again); extern void ceph_check_caps(struct ceph_inode_info *ci, int flags, struct ceph_mds_session *session); extern void ceph_check_delayed_caps(struct ceph_mds_client *mdsc); diff --git a/fs/char_dev.c b/fs/char_dev.c index f80a4f2..143d393 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -40,7 +40,9 @@ struct backing_dev_info directly_mappable_cdev_bdi = { #endif /* permit direct mmap, for read, write or exec */ BDI_CAP_MAP_DIRECT | - BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP), + BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP | + /* no writeback happens */ + BDI_CAP_NO_ACCT_AND_WRITEBACK), }; static struct kobj_map *cdev_map; diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0da1deb..917b7d4 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -2,8 +2,6 @@ config CIFS tristate "CIFS support (advanced network filesystem, SMBFS successor)" depends on INET select NLS - select CRYPTO_MD5 - select CRYPTO_ARC4 help This is the client VFS module for the Common Internet File System (CIFS) protocol which is the successor to the Server Message Block diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 21f0fbd..cfd1ce3 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, if (compare_oid(oid, oidlen, MSKRB5_OID, MSKRB5_OID_LEN)) server->sec_mskerberos = true; - if (compare_oid(oid, oidlen, KRB5U2U_OID, + else if (compare_oid(oid, oidlen, KRB5U2U_OID, KRB5U2U_OID_LEN)) server->sec_kerberosu2u = true; - if (compare_oid(oid, oidlen, KRB5_OID, + else if (compare_oid(oid, oidlen, KRB5_OID, KRB5_OID_LEN)) server->sec_kerberos = true; - if (compare_oid(oid, oidlen, NTLMSSP_OID, + else if (compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN)) server->sec_ntlmssp = true; diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 709f229..35042d8 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -27,7 +27,6 @@ #include "md5.h" #include "cifs_unicode.h" #include "cifsproto.h" -#include "ntlmssp.h" #include <linux/ctype.h> #include <linux/random.h> @@ -43,43 +42,21 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24); static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, - struct TCP_Server_Info *server, char *signature) + const struct mac_key *key, char *signature) { - int rc; + struct MD5Context context; - if (cifs_pdu == NULL || server == NULL || signature == NULL) + if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) return -EINVAL; - if (!server->ntlmssp.sdescmd5) { - cERROR(1, - "cifs_calculate_signature: can't generate signature\n"); - return -1; - } - - rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); - if (rc) { - cERROR(1, "cifs_calculate_signature: oould not init md5\n"); - return rc; - } - - if (server->secType == RawNTLMSSP) - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - server->session_key.data.ntlmv2.key, - CIFS_NTLMV2_SESSKEY_SIZE); - else - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - (char *)&server->session_key.data, - server->session_key.len); - - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - cifs_pdu->Protocol, cifs_pdu->smb_buf_length); + cifs_MD5_init(&context); + cifs_MD5_update(&context, (char *)&key->data, key->len); + cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); - rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); - - return rc; + cifs_MD5_final(signature, &context); + return 0; } - int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) { @@ -101,7 +78,8 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, server->sequence_number++; spin_unlock(&GlobalMid_Lock); - rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); + rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, + smb_signature); if (rc) memset(cifs_pdu->Signature.SecuritySignature, 0, 8); else @@ -111,39 +89,21 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, } static int cifs_calc_signature2(const struct kvec *iov, int n_vec, - struct TCP_Server_Info *server, char *signature) + const struct mac_key *key, char *signature) { + struct MD5Context context; int i; - int rc; - if (iov == NULL || server == NULL || signature == NULL) + if ((iov == NULL) || (signature == NULL) || (key == NULL)) return -EINVAL; - if (!server->ntlmssp.sdescmd5) { - cERROR(1, "cifs_calc_signature2: can't generate signature\n"); - return -1; - } - - rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); - if (rc) { - cERROR(1, "cifs_calc_signature2: oould not init md5\n"); - return rc; - } - - if (server->secType == RawNTLMSSP) - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - server->session_key.data.ntlmv2.key, - CIFS_NTLMV2_SESSKEY_SIZE); - else - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - (char *)&server->session_key.data, - server->session_key.len); - + cifs_MD5_init(&context); + cifs_MD5_update(&context, (char *)&key->data, key->len); for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { - cERROR(1, "cifs_calc_signature2: null iovec entry"); + cERROR(1, "null iovec entry"); return -EIO; } /* The first entry includes a length field (which does not get @@ -151,18 +111,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - iov[i].iov_base + 4, iov[i].iov_len - 4); + cifs_MD5_update(&context, iov[0].iov_base+4, + iov[0].iov_len-4); } else - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - iov[i].iov_base, iov[i].iov_len); + cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); } - rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); + cifs_MD5_final(signature, &context); - return rc; + return 0; } + int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) { @@ -185,7 +145,8 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, server->sequence_number++; spin_unlock(&GlobalMid_Lock); - rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); + rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, + smb_signature); if (rc) memset(cifs_pdu->Signature.SecuritySignature, 0, 8); else @@ -195,14 +156,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, } int cifs_verify_signature(struct smb_hdr *cifs_pdu, - struct TCP_Server_Info *server, + const struct mac_key *mac_key, __u32 expected_sequence_number) { - int rc; + unsigned int rc; char server_response_sig[8]; char what_we_think_sig_should_be[20]; - if (cifs_pdu == NULL || server == NULL) + if ((cifs_pdu == NULL) || (mac_key == NULL)) return -EINVAL; if (cifs_pdu->Command == SMB_COM_NEGOTIATE) @@ -231,7 +192,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, cpu_to_le32(expected_sequence_number); cifs_pdu->Signature.Sequence.Reserved = 0; - rc = cifs_calculate_signature(cifs_pdu, server, + rc = cifs_calculate_signature(cifs_pdu, mac_key, what_we_think_sig_should_be); if (rc) @@ -248,7 +209,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, } /* We fill in key by putting in 40 byte array which was allocated by caller */ -int cifs_calculate_session_key(struct session_key *key, const char *rn, +int cifs_calculate_mac_key(struct mac_key *key, const char *rn, const char *password) { char temp_key[16]; @@ -306,52 +267,38 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, { int rc = 0; int len; - char nt_hash[CIFS_NTHASH_SIZE]; + char nt_hash[16]; + struct HMACMD5Context *pctxt; wchar_t *user; wchar_t *domain; - wchar_t *server; - if (!ses->server->ntlmssp.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } + pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); + + if (pctxt == NULL) + return -ENOMEM; /* calculate md4 hash of password */ E_md4hash(ses->password, nt_hash); - crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash, - CIFS_NTHASH_SIZE); - - rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n"); - return rc; - } + /* convert Domainname to unicode and uppercase */ + hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); /* convert ses->userName to unicode and uppercase */ len = strlen(ses->userName); user = kmalloc(2 + (len * 2), GFP_KERNEL); - if (user == NULL) { - cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); - rc = -ENOMEM; + if (user == NULL) goto calc_exit_2; - } len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); UniStrupr(user); - - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - (char *)user, 2 * len); + hmac_md5_update((char *)user, 2*len, pctxt); /* convert ses->domainName to unicode and uppercase */ if (ses->domainName) { len = strlen(ses->domainName); domain = kmalloc(2 + (len * 2), GFP_KERNEL); - if (domain == NULL) { - cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); - rc = -ENOMEM; + if (domain == NULL) goto calc_exit_1; - } len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, nls_cp); /* the following line was removed since it didn't work well @@ -359,292 +306,65 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, Maybe converting the domain name earlier makes sense */ /* UniStrupr(domain); */ - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - (char *)domain, 2 * len); + hmac_md5_update((char *)domain, 2*len, pctxt); kfree(domain); - } else if (ses->serverName) { - len = strlen(ses->serverName); - - server = kmalloc(2 + (len * 2), GFP_KERNEL); - if (server == NULL) { - cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); - rc = -ENOMEM; - goto calc_exit_1; - } - len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, - nls_cp); - /* the following line was removed since it didn't work well - with lower cased domain name that passed as an option. - Maybe converting the domain name earlier makes sense */ - /* UniStrupr(domain); */ - - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - (char *)server, 2 * len); - - kfree(server); } - - rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, - ses->server->ntlmv2_hash); - calc_exit_1: kfree(user); calc_exit_2: /* BB FIXME what about bytes 24 through 40 of the signing key? compare with the NTLM example */ + hmac_md5_final(ses->server->ntlmv2_hash, pctxt); + kfree(pctxt); return rc; } -static int -find_domain_name(struct cifsSesInfo *ses) -{ - int rc = 0; - unsigned int attrsize; - unsigned int type; - unsigned char *blobptr; - struct ntlmssp2_name *attrptr; - - if (ses->server->tiblob) { - blobptr = ses->server->tiblob; - attrptr = (struct ntlmssp2_name *) blobptr; - - while ((type = attrptr->type) != 0) { - blobptr += 2; /* advance attr type */ - attrsize = attrptr->length; - blobptr += 2; /* advance attr size */ - if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { - if (!ses->domainName) { - ses->domainName = - kmalloc(attrptr->length + 1, - GFP_KERNEL); - if (!ses->domainName) - return -ENOMEM; - cifs_from_ucs2(ses->domainName, - (__le16 *)blobptr, - attrptr->length, - attrptr->length, - load_nls_default(), false); - } - } - blobptr += attrsize; /* advance attr value */ - attrptr = (struct ntlmssp2_name *) blobptr; - } - } else { - ses->server->tilen = 2 * sizeof(struct ntlmssp2_name); - ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL); - if (!ses->server->tiblob) { - ses->server->tilen = 0; - cERROR(1, "Challenge target info allocation failure"); - return -ENOMEM; - } - memset(ses->server->tiblob, 0x0, ses->server->tilen); - attrptr = (struct ntlmssp2_name *) ses->server->tiblob; - attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); - } - - return rc; -} - -static int -CalcNTLMv2_response(const struct TCP_Server_Info *server, - char *v2_session_response) -{ - int rc; - - if (!server->ntlmssp.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } - - crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash, - CIFS_HMAC_MD5_HASH_SIZE); - - rc = crypto_shash_init(&server->ntlmssp.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "CalcNTLMv2_response: could not init hmacmd5"); - return rc; - } - - memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, - server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE); - crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, - v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, - sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE); - - if (server->tilen) - crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, - server->tiblob, server->tilen); - - rc = crypto_shash_final(&server->ntlmssp.sdeschmacmd5->shash, - v2_session_response); - - return rc; -} - -int -setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, +void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, const struct nls_table *nls_cp) { - int rc = 0; + int rc; struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; + struct HMACMD5Context context; buf->blob_signature = cpu_to_le32(0x00000101); buf->reserved = 0; buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); buf->reserved2 = 0; - - if (!ses->domainName) { - rc = find_domain_name(ses); - if (rc) { - cERROR(1, "could not get domain/server name rc %d", rc); - return rc; - } - } + buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); + buf->names[0].length = 0; + buf->names[1].type = 0; + buf->names[1].length = 0; /* calculate buf->ntlmv2_hash */ rc = calc_ntlmv2_hash(ses, nls_cp); - if (rc) { - cERROR(1, "could not get v2 hash rc %d", rc); - return rc; - } - rc = CalcNTLMv2_response(ses->server, resp_buf); - if (rc) { + if (rc) cERROR(1, "could not get v2 hash rc %d", rc); - return rc; - } - - if (!ses->server->ntlmssp.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } - - crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, - ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); + CalcNTLMv2_response(ses, resp_buf); - rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n"); - return rc; - } + /* now calculate the MAC key for NTLMv2 */ + hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); + hmac_md5_update(resp_buf, 16, &context); + hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - resp_buf, CIFS_HMAC_MD5_HASH_SIZE); - - rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, - ses->server->session_key.data.ntlmv2.key); - - memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf, - sizeof(struct ntlmv2_resp)); - ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp); - - return rc; + memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, + sizeof(struct ntlmv2_resp)); + ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); } -int -calc_seckey(struct TCP_Server_Info *server) -{ - int rc; - unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE]; - struct crypto_blkcipher *tfm_arc4; - struct scatterlist sgin, sgout; - struct blkcipher_desc desc; - - get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE); - - tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", - 0, CRYPTO_ALG_ASYNC); - if (!tfm_arc4 || IS_ERR(tfm_arc4)) { - cERROR(1, "could not allocate " "master crypto API arc4\n"); - return 1; - } - - desc.tfm = tfm_arc4; - - crypto_blkcipher_setkey(tfm_arc4, - server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE); - sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE); - sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); - rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); - - if (!rc) - memcpy(server->session_key.data.ntlmv2.key, - sec_key, CIFS_NTLMV2_SESSKEY_SIZE); - - crypto_free_blkcipher(tfm_arc4); - - return 0; -} - -void -cifs_crypto_shash_release(struct TCP_Server_Info *server) -{ - if (server->ntlmssp.md5) - crypto_free_shash(server->ntlmssp.md5); - - if (server->ntlmssp.hmacmd5) - crypto_free_shash(server->ntlmssp.hmacmd5); - - kfree(server->ntlmssp.sdeschmacmd5); - - kfree(server->ntlmssp.sdescmd5); -} - -int -cifs_crypto_shash_allocate(struct TCP_Server_Info *server) +void CalcNTLMv2_response(const struct cifsSesInfo *ses, + char *v2_session_response) { - int rc; - unsigned int size; - - server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); - if (!server->ntlmssp.hmacmd5 || - IS_ERR(server->ntlmssp.hmacmd5)) { - cERROR(1, "could not allocate crypto hmacmd5\n"); - return 1; - } - - server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0); - if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) { - cERROR(1, "could not allocate crypto md5\n"); - rc = 1; - goto cifs_crypto_shash_allocate_ret1; - } - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->ntlmssp.hmacmd5); - server->ntlmssp.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); - if (!server->ntlmssp.sdeschmacmd5) { - cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n"); - rc = -ENOMEM; - goto cifs_crypto_shash_allocate_ret2; - } - server->ntlmssp.sdeschmacmd5->shash.tfm = server->ntlmssp.hmacmd5; - server->ntlmssp.sdeschmacmd5->shash.flags = 0x0; + struct HMACMD5Context context; + /* rest of v2 struct already generated */ + memcpy(v2_session_response + 8, ses->server->cryptKey, 8); + hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); + hmac_md5_update(v2_session_response+8, + sizeof(struct ntlmv2_resp) - 8, &context); - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->ntlmssp.md5); - server->ntlmssp.sdescmd5 = kmalloc(size, GFP_KERNEL); - if (!server->ntlmssp.sdescmd5) { - cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n"); - rc = -ENOMEM; - goto cifs_crypto_shash_allocate_ret3; - } - server->ntlmssp.sdescmd5->shash.tfm = server->ntlmssp.md5; - server->ntlmssp.sdescmd5->shash.flags = 0x0; - - return 0; - -cifs_crypto_shash_allocate_ret3: - kfree(server->ntlmssp.sdeschmacmd5); - -cifs_crypto_shash_allocate_ret2: - crypto_free_shash(server->ntlmssp.md5); - -cifs_crypto_shash_allocate_ret1: - crypto_free_shash(server->ntlmssp.hmacmd5); - - return rc; + hmac_md5_final(v2_session_response, &context); +/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c9d0cfc..0cdfb8c 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -25,9 +25,6 @@ #include <linux/workqueue.h> #include "cifs_fs_sb.h" #include "cifsacl.h" -#include <crypto/internal/hash.h> -#include <linux/scatterlist.h> - /* * The sizes of various internal tables and strings */ @@ -100,7 +97,7 @@ enum protocolEnum { /* Netbios frames protocol not supported at this time */ }; -struct session_key { +struct mac_key { unsigned int len; union { char ntlm[CIFS_SESS_KEY_SIZE + 16]; @@ -123,21 +120,6 @@ struct cifs_cred { struct cifs_ace *aces; }; -struct sdesc { - struct shash_desc shash; - char ctx[]; -}; - -struct ntlmssp_auth { - __u32 client_flags; - __u32 server_flags; - unsigned char ciphertext[CIFS_CPHTXT_SIZE]; - struct crypto_shash *hmacmd5; - struct crypto_shash *md5; - struct sdesc *sdeschmacmd5; - struct sdesc *sdescmd5; -}; - /* ***************************************************************** * Except the CIFS PDUs themselves all the @@ -200,14 +182,11 @@ struct TCP_Server_Info { /* 16th byte of RFC1001 workstation name is always null */ char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; __u32 sequence_number; /* needed for CIFS PDU signature */ - struct session_key session_key; + struct mac_key mac_signing_key; char ntlmv2_hash[16]; unsigned long lstrp; /* when we got last response from this server */ u16 dialect; /* dialect index that server chose */ /* extended security flavors that server supports */ - unsigned int tilen; /* length of the target info blob */ - unsigned char *tiblob; /* target info blob in challenge response */ - struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */ bool sec_kerberos; /* supports plain Kerberos */ bool sec_mskerberos; /* supports legacy MS Kerberos */ bool sec_kerberosu2u; /* supports U2U Kerberos */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 320e0fd..14d036d 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -134,12 +134,6 @@ * Size of the session key (crypto key encrypted with the password */ #define CIFS_SESS_KEY_SIZE (24) -#define CIFS_CLIENT_CHALLENGE_SIZE (8) -#define CIFS_SERVER_CHALLENGE_SIZE (8) -#define CIFS_HMAC_MD5_HASH_SIZE (16) -#define CIFS_CPHTXT_SIZE (16) -#define CIFS_NTLMV2_SESSKEY_SIZE (16) -#define CIFS_NTHASH_SIZE (16) /* * Maximum user name length @@ -669,6 +663,7 @@ struct ntlmv2_resp { __le64 time; __u64 client_chal; /* random */ __u32 reserved2; + struct ntlmssp2_name names[2]; /* array of name entries could follow ending in minimum 4 byte struct */ } __attribute__((packed)); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1378d91..1d60c65 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern int decode_negTokenInit(unsigned char *security_blob, int length, struct TCP_Server_Info *server); extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); +extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, - unsigned short int port); + const unsigned short int port); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifsTconInfo *, int /* length of @@ -361,15 +362,13 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, __u32 *); extern int cifs_verify_signature(struct smb_hdr *, - struct TCP_Server_Info *server, + const struct mac_key *mac_key, __u32 expected_sequence_number); -extern int cifs_calculate_session_key(struct session_key *key, const char *rn, +extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, const char *pass); -extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, +extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); +extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, const struct nls_table *); -extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); -extern void cifs_crypto_shash_release(struct TCP_Server_Info *); -extern int calc_seckey(struct TCP_Server_Info *); #ifdef CONFIG_CIFS_WEAK_PW_HASH extern void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, char *lnm_session_key); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4bda920..7e83b35 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -232,7 +232,7 @@ static int small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, void **request_buf) { - int rc = 0; + int rc; rc = cifs_reconnect_tcon(tcon, smb_command); if (rc) @@ -250,7 +250,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, if (tcon != NULL) cifs_stats_inc(&tcon->num_smbs_sent); - return rc; + return 0; } int @@ -281,16 +281,9 @@ small_smb_init_no_tc(const int smb_command, const int wct, /* If the return code is zero, this function must fill in request_buf pointer */ static int -smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, - void **request_buf /* returned */ , - void **response_buf /* returned */ ) +__smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, + void **request_buf, void **response_buf) { - int rc = 0; - - rc = cifs_reconnect_tcon(tcon, smb_command); - if (rc) - return rc; - *request_buf = cifs_buf_get(); if (*request_buf == NULL) { /* BB should we add a retry in here if not a writepage? */ @@ -309,7 +302,31 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, if (tcon != NULL) cifs_stats_inc(&tcon->num_smbs_sent); - return rc; + return 0; +} + +/* If the return code is zero, this function must fill in request_buf pointer */ +static int +smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, + void **request_buf, void **response_buf) +{ + int rc; + + rc = cifs_reconnect_tcon(tcon, smb_command); + if (rc) + return rc; + + return __smb_init(smb_command, wct, tcon, request_buf, response_buf); +} + +static int +smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon, + void **request_buf, void **response_buf) +{ + if (tcon->ses->need_reconnect || tcon->need_reconnect) + return -EHOSTDOWN; + + return __smb_init(smb_command, wct, tcon, request_buf, response_buf); } static int validate_t2(struct smb_t2_rsp *pSMB) @@ -604,14 +621,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) else rc = -EINVAL; - if (server->secType == Kerberos) { - if (!server->sec_kerberos && - !server->sec_mskerberos) - rc = -EOPNOTSUPP; - } else if (server->secType == RawNTLMSSP) { - if (!server->sec_ntlmssp) - rc = -EOPNOTSUPP; - } else + if (server->sec_kerberos || server->sec_mskerberos) + server->secType = Kerberos; + else if (server->sec_ntlmssp) + server->secType = RawNTLMSSP; + else rc = -EOPNOTSUPP; } } else @@ -4537,8 +4551,8 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon) cFYI(1, "In QFSUnixInfo"); QFSUnixRetry: - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon, + (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; @@ -4607,8 +4621,8 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) cFYI(1, "In SETFSUnixInfo"); SETFSUnixRetry: /* BB switch to small buf init to save memory */ - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon, + (void **) &pSMB, (void **) &pSMBr); if (rc) return rc; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ec0ea4a..88c84a3 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -400,7 +400,9 @@ incomplete_rcv: cFYI(1, "call to reconnect done"); csocket = server->ssocket; continue; - } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { + } else if (length == -ERESTARTSYS || + length == -EAGAIN || + length == -EINTR) { msleep(1); /* minimum sleep to prevent looping allowing socket to clear and app threads to set tcpStatus CifsNeedReconnect if server hung */ @@ -414,18 +416,6 @@ incomplete_rcv: } else continue; } else if (length <= 0) { - if (server->tcpStatus == CifsNew) { - cFYI(1, "tcp session abend after SMBnegprot"); - /* some servers kill the TCP session rather than - returning an SMB negprot error, in which - case reconnecting here is not going to help, - and so simply return error to mount */ - break; - } - if (!try_to_freeze() && (length == -EINTR)) { - cFYI(1, "cifsd thread killed"); - break; - } cFYI(1, "Reconnect after unexpected peek error %d", length); cifs_reconnect(server); @@ -466,27 +456,19 @@ incomplete_rcv: an error on SMB negprot response */ cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", pdu_length); - if (server->tcpStatus == CifsNew) { - /* if nack on negprot (rather than - ret of smb negprot error) reconnecting - not going to help, ret error to mount */ - break; - } else { - /* give server a second to - clean up before reconnect attempt */ - msleep(1000); - /* always try 445 first on reconnect - since we get NACK on some if we ever - connected to port 139 (the NACK is - since we do not begin with RFC1001 - session initialize frame) */ - server->addr.sockAddr.sin_port = - htons(CIFS_PORT); - cifs_reconnect(server); - csocket = server->ssocket; - wake_up(&server->response_q); - continue; - } + /* give server a second to clean up */ + msleep(1000); + /* always try 445 first on reconnect since we get NACK + * on some if we ever connected to port 139 (the NACK + * is since we do not begin with RFC1001 session + * initialize frame) + */ + cifs_set_port((struct sockaddr *) + &server->addr.sockAddr, CIFS_PORT); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; } else if (temp != (char) 0) { cERROR(1, "Unknown RFC 1002 frame"); cifs_dump_mem(" Received Data: ", (char *)smb_buffer, @@ -522,8 +504,7 @@ incomplete_rcv: total_read += length) { length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, pdu_length - total_read, 0); - if ((server->tcpStatus == CifsExiting) || - (length == -EINTR)) { + if (server->tcpStatus == CifsExiting) { /* then will exit */ reconnect = 2; break; @@ -534,8 +515,9 @@ incomplete_rcv: /* Now we will reread sock */ reconnect = 1; break; - } else if ((length == -ERESTARTSYS) || - (length == -EAGAIN)) { + } else if (length == -ERESTARTSYS || + length == -EAGAIN || + length == -EINTR) { msleep(1); /* minimum sleep to prevent looping, allowing socket to clear and app threads to set tcpStatus @@ -1708,7 +1690,6 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) CIFSSMBLogoff(xid, ses); _FreeXid(xid); } - cifs_crypto_shash_release(server); sesInfoFree(ses); cifs_put_tcp_session(server); } @@ -1725,9 +1706,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) if (ses) { cFYI(1, "Existing smb sess found (status=%d)", ses->status); - /* existing SMB ses has a server reference already */ - cifs_put_tcp_session(server); - mutex_lock(&ses->session_mutex); rc = cifs_negotiate_protocol(xid, ses); if (rc) { @@ -1750,6 +1728,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) } } mutex_unlock(&ses->session_mutex); + + /* existing SMB ses has a server reference already */ + cifs_put_tcp_session(server); FreeXid(xid); return ses; } @@ -1788,23 +1769,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) ses->linux_uid = volume_info->linux_uid; ses->overrideSecFlg = volume_info->secFlg; - rc = cifs_crypto_shash_allocate(server); - if (rc) { - cERROR(1, "could not setup hash structures rc %d", rc); - goto get_ses_fail; - } - server->tilen = 0; - server->tiblob = NULL; - mutex_lock(&ses->session_mutex); rc = cifs_negotiate_protocol(xid, ses); if (!rc) rc = cifs_setup_session(xid, ses, volume_info->local_nls); mutex_unlock(&ses->session_mutex); - if (rc) { - cifs_crypto_shash_release(ses->server); + if (rc) goto get_ses_fail; - } /* success, put it on the list */ write_lock(&cifs_tcp_ses_lock); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 86a164f..53cce8c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -801,6 +801,8 @@ retry_iget5_locked: inode->i_flags |= S_NOATIME | S_NOCMTIME; if (inode->i_state & I_NEW) { inode->i_ino = hash; + if (S_ISREG(inode->i_mode)) + inode->i_data.backing_dev_info = sb->s_bdi; #ifdef CONFIG_CIFS_FSCACHE /* initialize per-inode cache cookie pointer */ CIFS_I(inode)->fscache = NULL; @@ -1462,29 +1464,18 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, { char *fromName = NULL; char *toName = NULL; - struct cifs_sb_info *cifs_sb_source; - struct cifs_sb_info *cifs_sb_target; + struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; FILE_UNIX_BASIC_INFO *info_buf_source = NULL; FILE_UNIX_BASIC_INFO *info_buf_target; int xid, rc, tmprc; - cifs_sb_target = CIFS_SB(target_dir->i_sb); - cifs_sb_source = CIFS_SB(source_dir->i_sb); - tcon = cifs_sb_source->tcon; + cifs_sb = CIFS_SB(source_dir->i_sb); + tcon = cifs_sb->tcon; xid = GetXid(); /* - * BB: this might be allowed if same server, but different share. - * Consider adding support for this - */ - if (tcon != cifs_sb_target->tcon) { - rc = -EXDEV; - goto cifs_rename_exit; - } - - /* * we already have the rename sem so we do not need to * grab it again here to protect the path integrity */ @@ -1519,17 +1510,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, info_buf_target = info_buf_source + 1; tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, info_buf_source, - cifs_sb_source->local_nls, - cifs_sb_source->mnt_cifs_flags & + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (tmprc != 0) goto unlink_target; - tmprc = CIFSSMBUnixQPathInfo(xid, tcon, - toName, info_buf_target, - cifs_sb_target->local_nls, - /* remap based on source sb */ - cifs_sb_source->mnt_cifs_flags & + tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, + info_buf_target, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (tmprc == 0 && (info_buf_source->UniqueId == diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f978511..9aad47a 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) } int -cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, - const unsigned short int port) +cifs_set_port(struct sockaddr *addr, const unsigned short int port) { - if (!cifs_convert_address(dst, src, len)) - return 0; - - switch (dst->sa_family) { + switch (addr->sa_family) { case AF_INET: - ((struct sockaddr_in *)dst)->sin_port = htons(port); + ((struct sockaddr_in *)addr)->sin_port = htons(port); break; case AF_INET6: - ((struct sockaddr_in6 *)dst)->sin6_port = htons(port); + ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); break; default: return 0; } - return 1; } +int +cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, + const unsigned short int port) +{ + if (!cifs_convert_address(dst, src, len)) + return 0; + return cifs_set_port(dst, port); +} + /***************************************************************************** convert a NT status code to a dos class/code *****************************************************************************/ diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 1db0f07..49c9a4e 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h @@ -61,19 +61,6 @@ #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 #define NTLMSSP_NEGOTIATE_56 0x80000000 -/* Define AV Pair Field IDs */ -#define NTLMSSP_AV_EOL 0 -#define NTLMSSP_AV_NB_COMPUTER_NAME 1 -#define NTLMSSP_AV_NB_DOMAIN_NAME 2 -#define NTLMSSP_AV_DNS_COMPUTER_NAME 3 -#define NTLMSSP_AV_DNS_DOMAIN_NAME 4 -#define NTLMSSP_AV_DNS_TREE_NAME 5 -#define NTLMSSP_AV_FLAGS 6 -#define NTLMSSP_AV_TIMESTAMP 7 -#define NTLMSSP_AV_RESTRICTION 8 -#define NTLMSSP_AV_TARGET_NAME 9 -#define NTLMSSP_AV_CHANNEL_BINDINGS 10 - /* Although typedefs are not commonly used for structure definitions */ /* in the Linux kernel, in this particular case they are useful */ /* to more closely match the standards document for NTLMSSP from */ diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 795095f..0a57cb7 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -383,9 +383,6 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifsSesInfo *ses) { - unsigned int tioffset; /* challeng message target info area */ - unsigned int tilen; /* challeng message target info area length */ - CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; if (blob_len < sizeof(CHALLENGE_MESSAGE)) { @@ -408,20 +405,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, /* BB spec says that if AvId field of MsvAvTimestamp is populated then we must set the MIC field of the AUTHENTICATE_MESSAGE */ - ses->server->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags); - - tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); - tilen = cpu_to_le16(pblob->TargetInfoArray.Length); - ses->server->tilen = tilen; - if (tilen) { - ses->server->tiblob = kmalloc(tilen, GFP_KERNEL); - if (!ses->server->tiblob) { - cERROR(1, "Challenge target info allocation failure"); - return -ENOMEM; - } - memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen); - } - return 0; } @@ -442,13 +425,12 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, /* BB is NTLMV2 session security format easier to use here? */ flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | - NTLMSSP_NEGOTIATE_NTLM; + NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; if (ses->server->secMode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - flags |= NTLMSSP_NEGOTIATE_SIGN | - NTLMSSP_NEGOTIATE_KEY_XCH | - NTLMSSP_NEGOTIATE_EXTENDED_SEC; - } + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + flags |= NTLMSSP_NEGOTIATE_SIGN; + if (ses->server->secMode & SECMODE_SIGN_REQUIRED) + flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; sec_blob->NegotiateFlags |= cpu_to_le32(flags); @@ -469,12 +451,10 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, struct cifsSesInfo *ses, const struct nls_table *nls_cp, bool first) { - int rc; - unsigned int size; AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; __u32 flags; unsigned char *tmp; - struct ntlmv2_resp ntlmv2_response = {}; + char ntlm_session_key[CIFS_SESS_KEY_SIZE]; memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); sec_blob->MessageType = NtLmAuthenticate; @@ -497,25 +477,19 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, sec_blob->LmChallengeResponse.Length = 0; sec_blob->LmChallengeResponse.MaximumLength = 0; - sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); - rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); - if (rc) { - cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc); - goto setup_ntlmv2_ret; - } - size = sizeof(struct ntlmv2_resp); - memcpy(tmp, (char *)&ntlmv2_response, size); - tmp += size; - if (ses->server->tilen > 0) { - memcpy(tmp, ses->server->tiblob, ses->server->tilen); - tmp += ses->server->tilen; - } else - ses->server->tilen = 0; + /* calculate session key, BB what about adding similar ntlmv2 path? */ + SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); + if (first) + cifs_calculate_mac_key(&ses->server->mac_signing_key, + ntlm_session_key, ses->password); - sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + - ses->server->tilen); + memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); + sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); sec_blob->NtChallengeResponse.MaximumLength = - cpu_to_le16(size + ses->server->tilen); + cpu_to_le16(CIFS_SESS_KEY_SIZE); + + tmp += CIFS_SESS_KEY_SIZE; if (ses->domainName == NULL) { sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); @@ -527,6 +501,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, MAX_USERNAME_SIZE, nls_cp); len *= 2; /* unicode is 2 bytes each */ + len += 2; /* trailing null */ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->DomainName.Length = cpu_to_le16(len); sec_blob->DomainName.MaximumLength = cpu_to_le16(len); @@ -543,6 +518,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, len = cifs_strtoUCS((__le16 *)tmp, ses->userName, MAX_USERNAME_SIZE, nls_cp); len *= 2; /* unicode is 2 bytes each */ + len += 2; /* trailing null */ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->UserName.Length = cpu_to_le16(len); sec_blob->UserName.MaximumLength = cpu_to_le16(len); @@ -554,26 +530,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, sec_blob->WorkstationName.MaximumLength = 0; tmp += 2; - if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && - !calc_seckey(ses->server)) { - memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); - sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); - sec_blob->SessionKey.MaximumLength = - cpu_to_le16(CIFS_CPHTXT_SIZE); - tmp += CIFS_CPHTXT_SIZE; - } else { - sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->SessionKey.Length = 0; - sec_blob->SessionKey.MaximumLength = 0; - } - - ses->server->sequence_number = 0; - -setup_ntlmv2_ret: - if (ses->server->tilen > 0) - kfree(ses->server->tiblob); - + sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->SessionKey.Length = 0; + sec_blob->SessionKey.MaximumLength = 0; return tmp - pbuffer; } @@ -587,14 +546,15 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, return; } -static int setup_ntlmssp_auth_req(char *ntlmsspblob, +static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, struct cifsSesInfo *ses, const struct nls_table *nls, bool first_time) { int bloblen; - bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls, + bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, first_time); + pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen); return bloblen; } @@ -730,7 +690,7 @@ ssetup_ntlmssp_authenticate: if (first_time) /* should this be moved into common code with similar ntlmv2 path? */ - cifs_calculate_session_key(&ses->server->session_key, + cifs_calculate_mac_key(&ses->server->mac_signing_key, ntlm_session_key, ses->password); /* copy session key */ @@ -769,21 +729,12 @@ ssetup_ntlmssp_authenticate: cpu_to_le16(sizeof(struct ntlmv2_resp)); /* calculate session key */ - rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); - if (rc) { - kfree(v2_sess_key); - goto ssetup_exit; - } + setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); /* FIXME: calculate MAC key */ memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp)); bcc_ptr += sizeof(struct ntlmv2_resp); kfree(v2_sess_key); - if (ses->server->tilen > 0) { - memcpy(bcc_ptr, ses->server->tiblob, - ses->server->tilen); - bcc_ptr += ses->server->tilen; - } if (ses->capabilities & CAP_UNICODE) { if (iov[0].iov_len % 2) { *bcc_ptr = 0; @@ -814,15 +765,15 @@ ssetup_ntlmssp_authenticate: } /* bail out if key is too long */ if (msg->sesskey_len > - sizeof(ses->server->session_key.data.krb5)) { + sizeof(ses->server->mac_signing_key.data.krb5)) { cERROR(1, "Kerberos signing key too long (%u bytes)", msg->sesskey_len); rc = -EOVERFLOW; goto ssetup_exit; } if (first_time) { - ses->server->session_key.len = msg->sesskey_len; - memcpy(ses->server->session_key.data.krb5, + ses->server->mac_signing_key.len = msg->sesskey_len; + memcpy(ses->server->mac_signing_key.data.krb5, msg->data, msg->sesskey_len); } pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; @@ -864,28 +815,12 @@ ssetup_ntlmssp_authenticate: if (phase == NtLmNegotiate) { setup_ntlmssp_neg_req(pSMB, ses); iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); - iov[1].iov_base = &pSMB->req.SecurityBlob[0]; } else if (phase == NtLmAuthenticate) { int blob_len; - char *ntlmsspblob; - - ntlmsspblob = kmalloc(5 * - sizeof(struct _AUTHENTICATE_MESSAGE), - GFP_KERNEL); - if (!ntlmsspblob) { - cERROR(1, "Can't allocate NTLMSSP"); - rc = -ENOMEM; - goto ssetup_exit; - } - - blob_len = setup_ntlmssp_auth_req(ntlmsspblob, - ses, - nls_cp, - first_time); + blob_len = setup_ntlmssp_auth_req(pSMB, ses, + nls_cp, + first_time); iov[1].iov_len = blob_len; - iov[1].iov_base = ntlmsspblob; - pSMB->req.SecurityBlobLength = - cpu_to_le16(blob_len); /* Make sure that we tell the server that we are using the uid that it just gave us back on the response (challenge) */ @@ -895,6 +830,7 @@ ssetup_ntlmssp_authenticate: rc = -ENOSYS; goto ssetup_exit; } + iov[1].iov_base = &pSMB->req.SecurityBlob[0]; /* unicode strings must be word aligned */ if ((iov[0].iov_len + iov[1].iov_len) % 2) { *bcc_ptr = 0; diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index e0588cd..82f78c4 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { rc = cifs_verify_signature(midQ->resp_buf, - ses->server, + &ses->server->mac_signing_key, midQ->sequence_number+1); if (rc) { cERROR(1, "Unexpected SMB signature"); @@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { rc = cifs_verify_signature(out_buf, - ses->server, + &ses->server->mac_signing_key, midQ->sequence_number+1); if (rc) { cERROR(1, "Unexpected SMB signature"); @@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { rc = cifs_verify_signature(out_buf, - ses->server, + &ses->server->mac_signing_key, midQ->sequence_number+1); if (rc) { cERROR(1, "Unexpected SMB signature"); diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index de89645..116af75 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -184,8 +184,8 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf, } /* adjust outsize. is this useful ?? */ - req->uc_outSize = nbytes; - req->uc_flags |= REQ_WRITE; + req->uc_outSize = nbytes; + req->uc_flags |= CODA_REQ_WRITE; count = nbytes; /* Convert filedescriptor into a file handle */ diff --git a/fs/compat.c b/fs/compat.c index 718c706..0644a15 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1153,7 +1153,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov; + struct iovec *iov = iovstack; ssize_t ret; io_fn_t fn; iov_fn_t fnv; @@ -2014,3 +2014,41 @@ fail_creds: fail: return; } + +/* + * Core dumping helper functions. These are the only things you should + * do on a core-file: use only these functions to write out all the + * necessary info. + */ +int dump_write(struct file *file, const void *addr, int nr) +{ + return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; +} + +int dump_seek(struct file *file, loff_t off) +{ + int ret = 1; + + if (file->f_op->llseek && file->f_op->llseek != no_llseek) { + if (file->f_op->llseek(file, off, SEEK_CUR) < 0) + return 0; + } else { + char *buf = (char *)get_zeroed_page(GFP_KERNEL); + + if (!buf) + return 0; + while (off > 0) { + unsigned long n = off; + + if (n > PAGE_SIZE) + n = PAGE_SIZE; + if (!dump_write(file, buf, n)) { + ret = 0; + break; + } + off -= n; + } + free_page((unsigned long)buf); + } + return ret; +} diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index eb7368e..3eadd97 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -54,6 +54,9 @@ struct page_collect { unsigned nr_pages; unsigned long length; loff_t pg_first; /* keep 64bit also in 32-arches */ + bool read_4_write; /* This means two things: that the read is sync + * And the pages should not be unlocked. + */ }; static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, @@ -71,6 +74,7 @@ static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, pcol->nr_pages = 0; pcol->length = 0; pcol->pg_first = -1; + pcol->read_4_write = false; } static void _pcol_reset(struct page_collect *pcol) @@ -347,7 +351,8 @@ static int readpage_strip(void *data, struct page *page) if (PageError(page)) ClearPageError(page); - unlock_page(page); + if (!pcol->read_4_write) + unlock_page(page); EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page," " splitting\n", inode->i_ino, page->index); @@ -428,6 +433,7 @@ static int _readpage(struct page *page, bool is_sync) /* readpage_strip might call read_exec(,is_sync==false) at several * places but not if we have a single page. */ + pcol.read_4_write = is_sync; ret = readpage_strip(&pcol, page); if (ret) { EXOFS_ERR("_readpage => %d\n", ret); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 81e086d..ab38fef 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -52,8 +52,6 @@ struct wb_writeback_work { #define CREATE_TRACE_POINTS #include <trace/events/writeback.h> -#define inode_to_bdi(inode) ((inode)->i_mapping->backing_dev_info) - /* * We don't actually have pdflush, but this one is exported though /proc... */ @@ -71,6 +69,16 @@ int writeback_in_progress(struct backing_dev_info *bdi) return test_bit(BDI_writeback_running, &bdi->state); } +static inline struct backing_dev_info *inode_to_bdi(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + + if (strcmp(sb->s_type->name, "bdev") == 0) + return inode->i_mapping->backing_dev_info; + + return sb->s_bdi; +} + static void bdi_queue_work(struct backing_dev_info *bdi, struct wb_writeback_work *work) { diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index d367af1..cde755c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1354,7 +1354,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, loff_t file_size; unsigned int num; unsigned int offset; - size_t total_len; + size_t total_len = 0; req = fuse_get_req(fc); if (IS_ERR(req)) diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index cde1248..ac750bd 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -932,7 +932,7 @@ int gfs2_logd(void *data) do { prepare_to_wait(&sdp->sd_logd_waitq, &wait, - TASK_UNINTERRUPTIBLE); + TASK_INTERRUPTIBLE); if (!gfs2_ail_flush_reqd(sdp) && !gfs2_jrnl_flush_reqd(sdp) && !kthread_should_stop()) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 6c2aad4..f7e13db 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -63,6 +63,7 @@ config NFS_V3_ACL config NFS_V4 bool "NFS client support for NFS version 4" depends on NFS_FS + select SUNRPC_GSS help This option enables support for version 4 of the NFS protocol (RFC 3530) in the kernel's NFS client. diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4e7df2a..e734072 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -275,7 +275,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, sin1->sin6_scope_id != sin2->sin6_scope_id) return 0; - return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); + return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); } #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, diff --git a/fs/nfs/file.c b/fs/nfs/file.c index eb51bd6..05bf3c0 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -723,10 +723,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) default: BUG(); } - if (res < 0) - dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager" - " - error %d!\n", - __func__, res); return res; } diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ec3966e..f4cbf0c 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) goto out_err; error = server->nfs_client->rpc_ops->statfs(server, fh, &res); + if (unlikely(error == -ESTALE)) { + struct dentry *pd_dentry; + pd_dentry = dget_parent(dentry); + if (pd_dentry != NULL) { + nfs_zap_caches(pd_dentry->d_inode); + dput(pd_dentry); + } + } nfs_free_fattr(res.fattr); if (error < 0) goto out_err; diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 95932f5..4264377 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -69,6 +69,7 @@ config NFSD_V4 depends on NFSD && PROC_FS && EXPERIMENTAL select NFSD_V3 select FS_POSIX_ACL + select SUNRPC_GSS help This option enables support in your system's NFS server for version 4 of the NFS protocol (RFC 3530). diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h index cdfb8c6..c16f8d8 100644 --- a/fs/nfsd/nfsfh.h +++ b/fs/nfsd/nfsfh.h @@ -196,8 +196,6 @@ fh_lock(struct svc_fh *fhp) static inline void fh_unlock(struct svc_fh *fhp) { - BUG_ON(!fhp->fh_dentry); - if (fhp->fh_locked) { fill_post_wcc(fhp); mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex); diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig index 22c629e..b388443 100644 --- a/fs/notify/Kconfig +++ b/fs/notify/Kconfig @@ -3,4 +3,4 @@ config FSNOTIFY source "fs/notify/dnotify/Kconfig" source "fs/notify/inotify/Kconfig" -source "fs/notify/fanotify/Kconfig" +#source "fs/notify/fanotify/Kconfig" diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index a76e0aa..3919150 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -209,7 +209,10 @@ static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh, } inode->i_mode = new_mode; + inode->i_ctime = CURRENT_TIME; di->i_mode = cpu_to_le16(inode->i_mode); + di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); + di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); ocfs2_journal_dirty(handle, di_bh); diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 1361997..cbe2f05 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -977,7 +977,7 @@ static int o2net_tx_can_proceed(struct o2net_node *nn, int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, size_t caller_veclen, u8 target_node, int *status) { - int ret; + int ret = 0; struct o2net_msg *msg = NULL; size_t veclen, caller_bytes = 0; struct kvec *vec = NULL; diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index f04ebcf..c49f6de 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -3931,6 +3931,15 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, goto out_commit; } + cpos = split_hash; + ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle, + data_ac, meta_ac, new_dx_leaves, + num_dx_leaves); + if (ret) { + mlog_errno(ret); + goto out_commit; + } + for (i = 0; i < num_dx_leaves; i++) { ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), orig_dx_leaves[i], @@ -3939,15 +3948,14 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, mlog_errno(ret); goto out_commit; } - } - cpos = split_hash; - ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle, - data_ac, meta_ac, new_dx_leaves, - num_dx_leaves); - if (ret) { - mlog_errno(ret); - goto out_commit; + ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), + new_dx_leaves[i], + OCFS2_JOURNAL_ACCESS_WRITE); + if (ret) { + mlog_errno(ret); + goto out_commit; + } } ocfs2_dx_dir_transfer_leaf(dir, split_hash, handle, tmp_dx_leaf, diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index 4b6ae2c..7652989 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -1030,6 +1030,7 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res); void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node); +void dlm_force_free_mles(struct dlm_ctxt *dlm); int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock); int __dlm_lockres_has_locks(struct dlm_lock_resource *res); int __dlm_lockres_unused(struct dlm_lock_resource *res); diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c index 5efdd37..901ca52 100644 --- a/fs/ocfs2/dlm/dlmdebug.c +++ b/fs/ocfs2/dlm/dlmdebug.c @@ -636,8 +636,14 @@ static void *lockres_seq_start(struct seq_file *m, loff_t *pos) spin_lock(&dlm->track_lock); if (oldres) track_list = &oldres->tracking; - else + else { track_list = &dlm->tracking_list; + if (list_empty(track_list)) { + dl = NULL; + spin_unlock(&dlm->track_lock); + goto bail; + } + } list_for_each_entry(res, track_list, tracking) { if (&res->tracking == &dlm->tracking_list) @@ -660,6 +666,7 @@ static void *lockres_seq_start(struct seq_file *m, loff_t *pos) } else dl = NULL; +bail: /* passed to seq_show */ return dl; } diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 153abb5..11a5c87 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -693,6 +693,7 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) dlm_mark_domain_leaving(dlm); dlm_leave_domain(dlm); + dlm_force_free_mles(dlm); dlm_complete_dlm_shutdown(dlm); } dlm_put(dlm); diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index ffb4c68..f564b0e 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -3433,3 +3433,43 @@ void dlm_lockres_release_ast(struct dlm_ctxt *dlm, wake_up(&res->wq); wake_up(&dlm->migration_wq); } + +void dlm_force_free_mles(struct dlm_ctxt *dlm) +{ + int i; + struct hlist_head *bucket; + struct dlm_master_list_entry *mle; + struct hlist_node *tmp, *list; + + /* + * We notified all other nodes that we are exiting the domain and + * marked the dlm state to DLM_CTXT_LEAVING. If any mles are still + * around we force free them and wake any processes that are waiting + * on the mles + */ + spin_lock(&dlm->spinlock); + spin_lock(&dlm->master_lock); + + BUG_ON(dlm->dlm_state != DLM_CTXT_LEAVING); + BUG_ON((find_next_bit(dlm->domain_map, O2NM_MAX_NODES, 0) < O2NM_MAX_NODES)); + + for (i = 0; i < DLM_HASH_BUCKETS; i++) { + bucket = dlm_master_hash(dlm, i); + hlist_for_each_safe(list, tmp, bucket) { + mle = hlist_entry(list, struct dlm_master_list_entry, + master_hash_node); + if (mle->type != DLM_MLE_BLOCK) { + mlog(ML_ERROR, "bad mle: %p\n", mle); + dlm_print_one_mle(mle); + } + atomic_set(&mle->woken, 1); + wake_up(&mle->wq); + + __dlm_unlink_mle(dlm, mle); + __dlm_mle_detach_hb_events(dlm, mle); + __dlm_put_mle(mle); + } + } + spin_unlock(&dlm->master_lock); + spin_unlock(&dlm->spinlock); +} diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index d1ce48e..1d596d8 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h @@ -84,6 +84,7 @@ enum { OI_LS_PARENT, OI_LS_RENAME1, OI_LS_RENAME2, + OI_LS_REFLINK_TARGET, }; int ocfs2_dlm_init(struct ocfs2_super *osb); diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 33f1c9a..fa31d05 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -235,18 +235,31 @@ #define OCFS2_HAS_REFCOUNT_FL (0x0010) /* Inode attributes, keep in sync with EXT2 */ -#define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */ -#define OCFS2_UNRM_FL (0x00000002) /* Undelete */ -#define OCFS2_COMPR_FL (0x00000004) /* Compress file */ -#define OCFS2_SYNC_FL (0x00000008) /* Synchronous updates */ -#define OCFS2_IMMUTABLE_FL (0x00000010) /* Immutable file */ -#define OCFS2_APPEND_FL (0x00000020) /* writes to file may only append */ -#define OCFS2_NODUMP_FL (0x00000040) /* do not dump file */ -#define OCFS2_NOATIME_FL (0x00000080) /* do not update atime */ -#define OCFS2_DIRSYNC_FL (0x00010000) /* dirsync behaviour (directories only) */ - -#define OCFS2_FL_VISIBLE (0x000100FF) /* User visible flags */ -#define OCFS2_FL_MODIFIABLE (0x000100FF) /* User modifiable flags */ +#define OCFS2_SECRM_FL FS_SECRM_FL /* Secure deletion */ +#define OCFS2_UNRM_FL FS_UNRM_FL /* Undelete */ +#define OCFS2_COMPR_FL FS_COMPR_FL /* Compress file */ +#define OCFS2_SYNC_FL FS_SYNC_FL /* Synchronous updates */ +#define OCFS2_IMMUTABLE_FL FS_IMMUTABLE_FL /* Immutable file */ +#define OCFS2_APPEND_FL FS_APPEND_FL /* writes to file may only append */ +#define OCFS2_NODUMP_FL FS_NODUMP_FL /* do not dump file */ +#define OCFS2_NOATIME_FL FS_NOATIME_FL /* do not update atime */ +/* Reserved for compression usage... */ +#define OCFS2_DIRTY_FL FS_DIRTY_FL +#define OCFS2_COMPRBLK_FL FS_COMPRBLK_FL /* One or more compressed clusters */ +#define OCFS2_NOCOMP_FL FS_NOCOMP_FL /* Don't compress */ +#define OCFS2_ECOMPR_FL FS_ECOMPR_FL /* Compression error */ +/* End compression flags --- maybe not all used */ +#define OCFS2_BTREE_FL FS_BTREE_FL /* btree format dir */ +#define OCFS2_INDEX_FL FS_INDEX_FL /* hash-indexed directory */ +#define OCFS2_IMAGIC_FL FS_IMAGIC_FL /* AFS directory */ +#define OCFS2_JOURNAL_DATA_FL FS_JOURNAL_DATA_FL /* Reserved for ext3 */ +#define OCFS2_NOTAIL_FL FS_NOTAIL_FL /* file tail should not be merged */ +#define OCFS2_DIRSYNC_FL FS_DIRSYNC_FL /* dirsync behaviour (directories only) */ +#define OCFS2_TOPDIR_FL FS_TOPDIR_FL /* Top of directory hierarchies*/ +#define OCFS2_RESERVED_FL FS_RESERVED_FL /* reserved for ext2 lib */ + +#define OCFS2_FL_VISIBLE FS_FL_USER_VISIBLE /* User visible flags */ +#define OCFS2_FL_MODIFIABLE FS_FL_USER_MODIFIABLE /* User modifiable flags */ /* * Extent record flags (e_node.leaf.flags) diff --git a/fs/ocfs2/ocfs2_ioctl.h b/fs/ocfs2/ocfs2_ioctl.h index 2d3420a..5d24150 100644 --- a/fs/ocfs2/ocfs2_ioctl.h +++ b/fs/ocfs2/ocfs2_ioctl.h @@ -23,10 +23,10 @@ /* * ioctl commands */ -#define OCFS2_IOC_GETFLAGS _IOR('f', 1, long) -#define OCFS2_IOC_SETFLAGS _IOW('f', 2, long) -#define OCFS2_IOC32_GETFLAGS _IOR('f', 1, int) -#define OCFS2_IOC32_SETFLAGS _IOW('f', 2, int) +#define OCFS2_IOC_GETFLAGS FS_IOC_GETFLAGS +#define OCFS2_IOC_SETFLAGS FS_IOC_SETFLAGS +#define OCFS2_IOC32_GETFLAGS FS_IOC32_GETFLAGS +#define OCFS2_IOC32_SETFLAGS FS_IOC32_SETFLAGS /* * Space reservation / allocation / free ioctls and argument structure diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 0afeda831..efdd756 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -4201,8 +4201,9 @@ static int __ocfs2_reflink(struct dentry *old_dentry, goto out; } - mutex_lock(&new_inode->i_mutex); - ret = ocfs2_inode_lock(new_inode, &new_bh, 1); + mutex_lock_nested(&new_inode->i_mutex, I_MUTEX_CHILD); + ret = ocfs2_inode_lock_nested(new_inode, &new_bh, 1, + OI_LS_REFLINK_TARGET); if (ret) { mlog_errno(ret); goto out_unlock; diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c index d8b6e42..3e78db3 100644 --- a/fs/ocfs2/reservations.c +++ b/fs/ocfs2/reservations.c @@ -732,25 +732,23 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap, struct ocfs2_alloc_reservation *resv, int *cstart, int *clen) { - unsigned int wanted = *clen; - if (resv == NULL || ocfs2_resmap_disabled(resmap)) return -ENOSPC; spin_lock(&resv_lock); - /* - * We don't want to over-allocate for temporary - * windows. Otherwise, we run the risk of fragmenting the - * allocation space. - */ - wanted = ocfs2_resv_window_bits(resmap, resv); - if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen) - wanted = *clen; - if (ocfs2_resv_empty(resv)) { - mlog(0, "empty reservation, find new window\n"); + /* + * We don't want to over-allocate for temporary + * windows. Otherwise, we run the risk of fragmenting the + * allocation space. + */ + unsigned int wanted = ocfs2_resv_window_bits(resmap, resv); + if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen) + wanted = *clen; + + mlog(0, "empty reservation, find new window\n"); /* * Try to get a window here. If it works, we must fall * through and test the bitmap . This avoids some diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 8a286f5..849c2f0 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -357,7 +357,7 @@ out: static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb, struct ocfs2_group_desc *bg, struct ocfs2_chain_list *cl, - u64 p_blkno, u32 clusters) + u64 p_blkno, unsigned int clusters) { struct ocfs2_extent_list *el = &bg->bg_list; struct ocfs2_extent_rec *rec; @@ -369,7 +369,7 @@ static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb, rec->e_blkno = cpu_to_le64(p_blkno); rec->e_cpos = cpu_to_le32(le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc)); - rec->e_leaf_clusters = cpu_to_le32(clusters); + rec->e_leaf_clusters = cpu_to_le16(clusters); le16_add_cpu(&bg->bg_bits, clusters * le16_to_cpu(cl->cl_bpc)); le16_add_cpu(&bg->bg_free_bits_count, clusters * le16_to_cpu(cl->cl_bpc)); diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 32499d21..9975457 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -128,7 +128,7 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry, } /* Fast symlinks can't be large */ - len = strlen(target); + len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb)); link = kzalloc(len + 1, GFP_NOFS); if (!link) { status = -ENOMEM; diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index d03469f..06fa5e7 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -1286,13 +1286,11 @@ int ocfs2_xattr_get_nolock(struct inode *inode, xis.inode_bh = xbs.inode_bh = di_bh; di = (struct ocfs2_dinode *)di_bh->b_data; - down_read(&oi->ip_xattr_sem); ret = ocfs2_xattr_ibody_get(inode, name_index, name, buffer, buffer_size, &xis); if (ret == -ENODATA && di->i_xattr_loc) ret = ocfs2_xattr_block_get(inode, name_index, name, buffer, buffer_size, &xbs); - up_read(&oi->ip_xattr_sem); return ret; } @@ -1316,8 +1314,10 @@ static int ocfs2_xattr_get(struct inode *inode, mlog_errno(ret); return ret; } + down_read(&OCFS2_I(inode)->ip_xattr_sem); ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index, name, buffer, buffer_size); + up_read(&OCFS2_I(inode)->ip_xattr_sem); ocfs2_inode_unlock(inode, 0); diff --git a/fs/proc/base.c b/fs/proc/base.c index a1c43e7..8e4adda 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2675,7 +2675,7 @@ static const struct pid_entry tgid_base_stuff[] = { INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), ONE("personality", S_IRUSR, proc_pid_personality), - INF("limits", S_IRUSR, proc_pid_limits), + INF("limits", S_IRUGO, proc_pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif @@ -3011,7 +3011,7 @@ static const struct pid_entry tid_base_stuff[] = { INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), ONE("personality", S_IRUSR, proc_pid_personality), - INF("limits", S_IRUSR, proc_pid_limits), + INF("limits", S_IRUGO, proc_pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 271afc4..1dbca4e8 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -363,13 +363,13 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, mss->referenced += PAGE_SIZE; mapcount = page_mapcount(page); if (mapcount >= 2) { - if (pte_dirty(ptent)) + if (pte_dirty(ptent) || PageDirty(page)) mss->shared_dirty += PAGE_SIZE; else mss->shared_clean += PAGE_SIZE; mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount; } else { - if (pte_dirty(ptent)) + if (pte_dirty(ptent) || PageDirty(page)) mss->private_dirty += PAGE_SIZE; else mss->private_clean += PAGE_SIZE; diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 91c817f..2367fb3 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -163,7 +163,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer, static const struct file_operations proc_vmcore_operations = { .read = read_vmcore, - .llseek = generic_file_llseek, + .llseek = default_llseek, }; static struct vmcore* __init get_new_element(void) diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index f53505d..5cbb81e 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -170,6 +170,7 @@ int reiserfs_prepare_write(struct file *f, struct page *page, int reiserfs_unpack(struct inode *inode, struct file *filp) { int retval = 0; + int depth; int index; struct page *page; struct address_space *mapping; @@ -188,8 +189,8 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) /* we need to make sure nobody is changing the file size beneath ** us */ - mutex_lock(&inode->i_mutex); - reiserfs_write_lock(inode->i_sb); + reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); + depth = reiserfs_write_lock_once(inode->i_sb); write_from = inode->i_size & (blocksize - 1); /* if we are on a block boundary, we are already unpacked. */ @@ -224,6 +225,6 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) out: mutex_unlock(&inode->i_mutex); - reiserfs_write_unlock(inode->i_sb); + reiserfs_write_unlock_once(inode->i_sb, depth); return retval; } diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index d59c4a6..81976ff 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -668,14 +668,11 @@ xfs_inode_set_reclaim_tag( xfs_perag_put(pag); } -void -__xfs_inode_clear_reclaim_tag( - xfs_mount_t *mp, +STATIC void +__xfs_inode_clear_reclaim( xfs_perag_t *pag, xfs_inode_t *ip) { - radix_tree_tag_clear(&pag->pag_ici_root, - XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); pag->pag_ici_reclaimable--; if (!pag->pag_ici_reclaimable) { /* clear the reclaim tag from the perag radix tree */ @@ -689,6 +686,17 @@ __xfs_inode_clear_reclaim_tag( } } +void +__xfs_inode_clear_reclaim_tag( + xfs_mount_t *mp, + xfs_perag_t *pag, + xfs_inode_t *ip) +{ + radix_tree_tag_clear(&pag->pag_ici_root, + XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); + __xfs_inode_clear_reclaim(pag, ip); +} + /* * Inodes in different states need to be treated differently, and the return * value of xfs_iflush is not sufficient to get this right. The following table @@ -838,6 +846,7 @@ reclaim: if (!radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino))) ASSERT(0); + __xfs_inode_clear_reclaim(pag, ip); write_unlock(&pag->pag_ici_lock); /* diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index ed575fb..7e206fc 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -405,9 +405,15 @@ xlog_cil_push( new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_SLEEP|KM_NOFS); new_ctx->ticket = xlog_cil_ticket_alloc(log); - /* lock out transaction commit, but don't block on background push */ + /* + * Lock out transaction commit, but don't block for background pushes + * unless we are well over the CIL space limit. See the definition of + * XLOG_CIL_HARD_SPACE_LIMIT() for the full explanation of the logic + * used here. + */ if (!down_write_trylock(&cil->xc_ctx_lock)) { - if (!push_seq) + if (!push_seq && + cil->xc_ctx->space_used < XLOG_CIL_HARD_SPACE_LIMIT(log)) goto out_free_ticket; down_write(&cil->xc_ctx_lock); } @@ -422,7 +428,7 @@ xlog_cil_push( goto out_skip; /* check for a previously pushed seqeunce */ - if (push_seq < cil->xc_ctx->sequence) + if (push_seq && push_seq < cil->xc_ctx->sequence) goto out_skip; /* diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index ced52b9..edcdfe0 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -426,13 +426,13 @@ struct xfs_cil { }; /* - * The amount of log space we should the CIL to aggregate is difficult to size. - * Whatever we chose we have to make we can get a reservation for the log space - * effectively, that it is large enough to capture sufficient relogging to - * reduce log buffer IO significantly, but it is not too large for the log or - * induces too much latency when writing out through the iclogs. We track both - * space consumed and the number of vectors in the checkpoint context, so we - * need to decide which to use for limiting. + * The amount of log space we allow the CIL to aggregate is difficult to size. + * Whatever we choose, we have to make sure we can get a reservation for the + * log space effectively, that it is large enough to capture sufficient + * relogging to reduce log buffer IO significantly, but it is not too large for + * the log or induces too much latency when writing out through the iclogs. We + * track both space consumed and the number of vectors in the checkpoint + * context, so we need to decide which to use for limiting. * * Every log buffer we write out during a push needs a header reserved, which * is at least one sector and more for v2 logs. Hence we need a reservation of @@ -459,16 +459,21 @@ struct xfs_cil { * checkpoint transaction ticket is specific to the checkpoint context, rather * than the CIL itself. * - * With dynamic reservations, we can basically make up arbitrary limits for the - * checkpoint size so long as they don't violate any other size rules. Hence - * the initial maximum size for the checkpoint transaction will be set to a - * quarter of the log or 8MB, which ever is smaller. 8MB is an arbitrary limit - * right now based on the latency of writing out a large amount of data through - * the circular iclog buffers. + * With dynamic reservations, we can effectively make up arbitrary limits for + * the checkpoint size so long as they don't violate any other size rules. + * Recovery imposes a rule that no transaction exceed half the log, so we are + * limited by that. Furthermore, the log transaction reservation subsystem + * tries to keep 25% of the log free, so we need to keep below that limit or we + * risk running out of free log space to start any new transactions. + * + * In order to keep background CIL push efficient, we will set a lower + * threshold at which background pushing is attempted without blocking current + * transaction commits. A separate, higher bound defines when CIL pushes are + * enforced to ensure we stay within our maximum checkpoint size bounds. + * threshold, yet give us plenty of space for aggregation on large logs. */ - -#define XLOG_CIL_SPACE_LIMIT(log) \ - (min((log->l_logsize >> 2), (8 * 1024 * 1024))) +#define XLOG_CIL_SPACE_LIMIT(log) (log->l_logsize >> 3) +#define XLOG_CIL_HARD_SPACE_LIMIT(log) (3 * (log->l_logsize >> 4)) /* * The reservation head lsn is not made up of a cycle number and block number. diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index c0786d4..984cdc6 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -55,7 +55,7 @@ extern u8 acpi_gbl_permanent_mmap; /* - * Globals that are publically available, allowing for + * Globals that are publicly available, allowing for * run time configuration */ extern u32 acpi_dbg_level; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 7809d23..4c9461a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -612,7 +612,7 @@ struct drm_gem_object { struct kref refcount; /** Handle count of this object. Each handle also holds a reference */ - struct kref handlecount; + atomic_t handle_count; /* number of handles on this object */ /** Related drm device */ struct drm_device *dev; @@ -808,7 +808,6 @@ struct drm_driver { */ int (*gem_init_object) (struct drm_gem_object *obj); void (*gem_free_object) (struct drm_gem_object *obj); - void (*gem_free_object_unlocked) (struct drm_gem_object *obj); /* vga arb irq handler */ void (*vgaarb_irq)(struct drm_device *dev, bool state); @@ -1175,6 +1174,7 @@ extern int drm_release(struct inode *inode, struct file *filp); extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); extern void drm_vm_open_locked(struct vm_area_struct *vma); +extern void drm_vm_close_locked(struct vm_area_struct *vma); extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map); extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev); extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); @@ -1455,12 +1455,11 @@ int drm_gem_init(struct drm_device *dev); void drm_gem_destroy(struct drm_device *dev); void drm_gem_object_release(struct drm_gem_object *obj); void drm_gem_object_free(struct kref *kref); -void drm_gem_object_free_unlocked(struct kref *kref); struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, size_t size); int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size); -void drm_gem_object_handle_free(struct kref *kref); +void drm_gem_object_handle_free(struct drm_gem_object *obj); void drm_gem_vm_open(struct vm_area_struct *vma); void drm_gem_vm_close(struct vm_area_struct *vma); int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); @@ -1483,8 +1482,12 @@ drm_gem_object_unreference(struct drm_gem_object *obj) static inline void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) { - if (obj != NULL) - kref_put(&obj->refcount, drm_gem_object_free_unlocked); + if (obj != NULL) { + struct drm_device *dev = obj->dev; + mutex_lock(&dev->struct_mutex); + kref_put(&obj->refcount, drm_gem_object_free); + mutex_unlock(&dev->struct_mutex); + } } int drm_gem_handle_create(struct drm_file *file_priv, @@ -1495,7 +1498,7 @@ static inline void drm_gem_object_handle_reference(struct drm_gem_object *obj) { drm_gem_object_reference(obj); - kref_get(&obj->handlecount); + atomic_inc(&obj->handle_count); } static inline void @@ -1504,12 +1507,15 @@ drm_gem_object_handle_unreference(struct drm_gem_object *obj) if (obj == NULL) return; + if (atomic_read(&obj->handle_count) == 0) + return; /* * Must bump handle count first as this may be the last * ref, in which case the object would disappear before we * checked for a name */ - kref_put(&obj->handlecount, drm_gem_object_handle_free); + if (atomic_dec_and_test(&obj->handle_count)) + drm_gem_object_handle_free(obj); drm_gem_object_unreference(obj); } @@ -1519,12 +1525,17 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) if (obj == NULL) return; + if (atomic_read(&obj->handle_count) == 0) + return; + /* * Must bump handle count first as this may be the last * ref, in which case the object would disappear before we * checked for a name */ - kref_put(&obj->handlecount, drm_gem_object_handle_free); + + if (atomic_dec_and_test(&obj->handle_count)) + drm_gem_object_handle_free(obj); drm_gem_object_unreference_unlocked(obj); } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c9f3cc5..3e5a51a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -386,7 +386,15 @@ struct drm_connector_funcs { void (*dpms)(struct drm_connector *connector, int mode); void (*save)(struct drm_connector *connector); void (*restore)(struct drm_connector *connector); - enum drm_connector_status (*detect)(struct drm_connector *connector); + + /* Check to see if anything is attached to the connector. + * @force is set to false whilst polling, true when checking the + * connector due to user request. @force can be used by the driver + * to avoid expensive, destructive operations during automated + * probing. + */ + enum drm_connector_status (*detect)(struct drm_connector *connector, + bool force); int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); int (*set_property)(struct drm_connector *connector, struct drm_property *property, uint64_t val); diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 3a9940e..883c1d4 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -85,7 +85,6 @@ {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ - {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \ {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \ @@ -103,6 +102,7 @@ {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ {0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \ diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 267a86c..2040e6c 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -246,9 +246,11 @@ struct ttm_buffer_object { atomic_t reserved; - /** * Members protected by the bo::lock + * In addition, setting sync_obj to anything else + * than NULL requires bo::reserved to be held. This allows for + * checking NULL while reserved but not holding bo::lock. */ void *sync_obj_arg; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 626b629..4e8ea8c 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -118,7 +118,6 @@ header-y += eventpoll.h header-y += ext2_fs.h header-y += fadvise.h header-y += falloc.h -header-y += fanotify.h header-y += fb.h header-y += fcntl.h header-y += fd.h diff --git a/include/linux/compat.h b/include/linux/compat.h index 9ddc878..5778b55 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, const struct compat_iovec __user *uvector, unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, struct iovec **ret_pointer); + +extern void __user *compat_alloc_user_space(unsigned long len); + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/include/linux/coredump.h b/include/linux/coredump.h index 8ba66a9..ba4b85a 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -9,37 +9,7 @@ * These are the only things you should do on a core-file: use only these * functions to write out all the necessary info. */ -static inline int dump_write(struct file *file, const void *addr, int nr) -{ - return file->f_op->write(file, addr, nr, &file->f_pos) == nr; -} - -static inline int dump_seek(struct file *file, loff_t off) -{ - int ret = 1; - - if (file->f_op->llseek && file->f_op->llseek != no_llseek) { - if (file->f_op->llseek(file, off, SEEK_CUR) < 0) - return 0; - } else { - char *buf = (char *)get_zeroed_page(GFP_KERNEL); - - if (!buf) - return 0; - while (off > 0) { - unsigned long n = off; - - if (n > PAGE_SIZE) - n = PAGE_SIZE; - if (!dump_write(file, buf, n)) { - ret = 0; - break; - } - off -= n; - } - free_page((unsigned long)buf); - } - return ret; -} +extern int dump_write(struct file *file, const void *addr, int nr); +extern int dump_seek(struct file *file, loff_t off); #endif /* _LINUX_COREDUMP_H */ diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 36ca972..1be416b 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -53,6 +53,7 @@ struct cpuidle_state { #define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */ #define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */ #define CPUIDLE_FLAG_IGNORE (0x100) /* ignore during this idle period */ +#define CPUIDLE_FLAG_TLB_FLUSHED (0x200) /* tlb will be flushed */ #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index ce29b81..ba8319a 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -102,6 +102,9 @@ static inline u64 dma_get_mask(struct device *dev) return DMA_BIT_MASK(32); } +#ifdef ARCH_HAS_DMA_SET_COHERENT_MASK +int dma_set_coherent_mask(struct device *dev, u64 mask); +#else static inline int dma_set_coherent_mask(struct device *dev, u64 mask) { if (!dma_supported(dev, mask)) @@ -109,6 +112,7 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask) dev->coherent_dma_mask = mask; return 0; } +#endif extern u64 dma_get_required_mask(struct device *dev); diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index c61d4ca..e210649 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -548,7 +548,7 @@ static inline bool dma_dev_has_pq_continue(struct dma_device *dma) return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE; } -static unsigned short dma_dev_to_maxpq(struct dma_device *dma) +static inline unsigned short dma_dev_to_maxpq(struct dma_device *dma) { return dma->max_pq & ~DMA_HAS_PQ_CONTINUE; } diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 926b503..4fd978e 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -93,6 +93,7 @@ struct elevator_queue struct elevator_type *elevator_type; struct mutex sysfs_lock; struct hlist_head *hash; + unsigned int registered:1; }; /* diff --git a/include/linux/fs.h b/include/linux/fs.h index 76041b6..63d069b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1093,6 +1093,10 @@ struct file_lock { #include <linux/fcntl.h> +/* temporary stubs for BKL removal */ +#define lock_flocks() lock_kernel() +#define unlock_flocks() unlock_kernel() + extern void send_sigio(struct fown_struct *fown, int fd, int band); #ifdef CONFIG_FILE_LOCKING diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 03f616b..e41f7dd 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -13,6 +13,7 @@ #include <linux/errno.h> struct device; +struct gpio_chip; /* * Some platforms don't support the GPIO programming interface. diff --git a/include/linux/module.h b/include/linux/module.h index 8a6b9fd..aace066 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -686,17 +686,16 @@ extern int module_sysfs_initialized; #ifdef CONFIG_GENERIC_BUG -int module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *, +void module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *, struct module *); void module_bug_cleanup(struct module *); #else /* !CONFIG_GENERIC_BUG */ -static inline int module_bug_finalize(const Elf_Ehdr *hdr, +static inline void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) { - return 0; } static inline void module_bug_cleanup(struct module *mod) {} #endif /* CONFIG_GENERIC_BUG */ diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 59d0669..1235669 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -27,8 +27,6 @@ #define MAX_LINKS 32 -struct net; - struct sockaddr_nl { sa_family_t nl_family; /* AF_NETLINK */ unsigned short nl_pad; /* zero */ @@ -151,6 +149,8 @@ struct nlattr { #include <linux/capability.h> #include <linux/skbuff.h> +struct net; + static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb) { return (struct nlmsghdr *)skb->data; diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 791d510..50d8009 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -63,20 +63,20 @@ static inline bool netpoll_rx(struct sk_buff *skb) unsigned long flags; bool ret = false; - rcu_read_lock_bh(); + local_irq_save(flags); npinfo = rcu_dereference_bh(skb->dev->npinfo); if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags)) goto out; - spin_lock_irqsave(&npinfo->rx_lock, flags); + spin_lock(&npinfo->rx_lock); /* check rx_flags again with the lock held */ if (npinfo->rx_flags && __netpoll_rx(skb)) ret = true; - spin_unlock_irqrestore(&npinfo->rx_lock, flags); + spin_unlock(&npinfo->rx_lock); out: - rcu_read_unlock_bh(); + local_irq_restore(flags); return ret; } diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 10d3330..570fdde 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -393,6 +393,9 @@ #define PCI_DEVICE_ID_VLSI_82C147 0x0105 #define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 +/* AMD RD890 Chipset */ +#define PCI_DEVICE_ID_RD890_IOMMU 0x5a23 + #define PCI_VENDOR_ID_ADL 0x1005 #define PCI_DEVICE_ID_ADL_2301 0x2301 diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d50ba85..d1a9193 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -274,8 +274,14 @@ static inline int dquot_alloc_space(struct inode *inode, qsize_t nr) int ret; ret = dquot_alloc_space_nodirty(inode, nr); - if (!ret) - mark_inode_dirty_sync(inode); + if (!ret) { + /* + * Mark inode fully dirty. Since we are allocating blocks, inode + * would become fully dirty soon anyway and it reportedly + * reduces inode_lock contention. + */ + mark_inode_dirty(inode); + } return ret; } diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 9fbc54a..83af1f8 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -454,7 +454,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) * Makes rcu_dereference_check() do the dirty work. */ #define rcu_dereference_bh(p) \ - rcu_dereference_check(p, rcu_read_lock_bh_held()) + rcu_dereference_check(p, rcu_read_lock_bh_held() || irqs_disabled()) /** * rcu_dereference_sched - fetch RCU-protected pointer, checking for RCU-sched diff --git a/include/linux/socket.h b/include/linux/socket.h index a2fada9..a8f56e1 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -322,7 +322,7 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata, int offset, unsigned int len, __wsum *csump); -extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode); +extern long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode); extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, int offset, int len); diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h index cc813f9..c91302f 100644 --- a/include/linux/spi/dw_spi.h +++ b/include/linux/spi/dw_spi.h @@ -14,7 +14,9 @@ #define SPI_MODE_OFFSET 6 #define SPI_SCPH_OFFSET 6 #define SPI_SCOL_OFFSET 7 + #define SPI_TMOD_OFFSET 8 +#define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET) #define SPI_TMOD_TR 0x0 /* xmit & recv */ #define SPI_TMOD_TO 0x1 /* xmit only */ #define SPI_TMOD_RO 0x2 /* recv only */ diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 569dc72..85f38a63 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -30,7 +30,7 @@ struct rpc_inode; * The high-level client handle */ struct rpc_clnt { - struct kref cl_kref; /* Number of references */ + atomic_t cl_count; /* Number of references */ struct list_head cl_clients; /* Global list of clients */ struct list_head cl_tasks; /* List of tasks */ spinlock_t cl_lock; /* spinlock */ diff --git a/include/linux/wait.h b/include/linux/wait.h index 0836ccc..3efc9f3 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -614,6 +614,7 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); (wait)->private = current; \ (wait)->func = autoremove_wake_function; \ INIT_LIST_HEAD(&(wait)->task_list); \ + (wait)->flags = 0; \ } while (0) /** diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index f11100f..25e02c9 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -235,6 +235,10 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } #define work_clear_pending(work) \ clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)) +/* + * Workqueue flags and constants. For details, please refer to + * Documentation/workqueue.txt. + */ enum { WQ_NON_REENTRANT = 1 << 0, /* guarantee non-reentrance */ WQ_UNBOUND = 1 << 1, /* not bound to any cpu */ diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h index 97e07f4..aa4ebb4 100644 --- a/include/media/videobuf-dma-sg.h +++ b/include/media/videobuf-dma-sg.h @@ -48,6 +48,7 @@ struct videobuf_dmabuf { /* for userland buffer */ int offset; + size_t size; struct page **pages; /* for kernel buffers */ diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 45375b4..4d40c4d 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -121,6 +121,7 @@ static inline int addrconf_finite_timeout(unsigned long timeout) * IPv6 Address Label subsystem (addrlabel.c) */ extern int ipv6_addr_label_init(void); +extern void ipv6_addr_label_cleanup(void); extern void ipv6_addr_label_rtnl_register(void); extern u32 ipv6_addr_label(struct net *net, const struct in6_addr *addr, diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 27a902d..30fce01 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -161,12 +161,30 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, unsigned long l { struct sk_buff *skb; + release_sock(sk); if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) { skb_reserve(skb, BT_SKB_RESERVE); bt_cb(skb)->incoming = 0; } + lock_sock(sk); + + if (!skb && *err) + return NULL; + + *err = sock_error(sk); + if (*err) + goto out; + + if (sk->sk_shutdown) { + *err = -ECONNRESET; + goto out; + } return skb; + +out: + kfree_skb(skb); + return NULL; } int bt_err(__u16 code); diff --git a/include/net/dst.h b/include/net/dst.h index 81d1413..0238650 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -242,6 +242,7 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; skb->rxhash = 0; + skb_set_queue_mapping(skb, 0); skb_dst_drop(skb); nf_reset(skb); } diff --git a/include/net/route.h b/include/net/route.h index bd732d6..7e5e73b 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -199,6 +199,8 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol, fl.fl_ip_sport = sport; fl.fl_ip_dport = dport; fl.proto = protocol; + if (inet_sk(sk)->transparent) + fl.flags |= FLOWI_FLAG_ANYSRC; ip_rt_put(*rp); *rp = NULL; security_sk_classify_flow(sk, &fl); diff --git a/include/net/tcp.h b/include/net/tcp.h index eaa9582..3e4b33e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -475,8 +475,22 @@ extern unsigned int tcp_current_mss(struct sock *sk); /* Bound MSS / TSO packet size with the half of the window */ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) { - if (tp->max_window && pktsize > (tp->max_window >> 1)) - return max(tp->max_window >> 1, 68U - tp->tcp_header_len); + int cutoff; + + /* When peer uses tiny windows, there is no use in packetizing + * to sub-MSS pieces for the sake of SWS or making sure there + * are enough packets in the pipe for fast recovery. + * + * On the other hand, for extremely large MSS devices, handling + * smaller than MSS windows in this way does make sense. + */ + if (tp->max_window >= 512) + cutoff = (tp->max_window >> 1); + else + cutoff = tp->max_window; + + if (cutoff && pktsize > cutoff) + return max_t(int, cutoff, 68U - tp->tcp_header_len); else return pktsize; } diff --git a/include/net/xfrm.h b/include/net/xfrm.h index fc8f36d..4f53532 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -298,8 +298,8 @@ struct xfrm_state_afinfo { const struct xfrm_type *type_map[IPPROTO_MAX]; struct xfrm_mode *mode_map[XFRM_MODE_MAX]; int (*init_flags)(struct xfrm_state *x); - void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, - struct xfrm_tmpl *tmpl, + void (*init_tempsel)(struct xfrm_selector *sel, struct flowi *fl); + void (*init_temprop)(struct xfrm_state *x, struct xfrm_tmpl *tmpl, xfrm_address_t *daddr, xfrm_address_t *saddr); int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); @@ -743,6 +743,8 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, { struct semid_ds out; + memset(&out, 0, sizeof(out)); + ipc64_perm_to_ipc_perm(&in->sem_perm, &out.sem_perm); out.sem_otime = in->sem_otime; diff --git a/kernel/compat.c b/kernel/compat.c index e167efc..c9e2ec0 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) return 0; } + +/* + * Allocate user-space memory for the duration of a single system call, + * in order to marshall parameters inside a compat thunk. + */ +void __user *compat_alloc_user_space(unsigned long len) +{ + void __user *ptr; + + /* If len would occupy more than half of the entire compat space... */ + if (unlikely(len > (((compat_uptr_t)~0) >> 1))) + return NULL; + + ptr = arch_compat_alloc_user_space(len); + + if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) + return NULL; + + return ptr; +} +EXPORT_SYMBOL_GPL(compat_alloc_user_space); diff --git a/kernel/fork.c b/kernel/fork.c index b7e9d60..c445f8c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -356,10 +356,10 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) if (IS_ERR(pol)) goto fail_nomem_policy; vma_set_policy(tmp, pol); + tmp->vm_mm = mm; if (anon_vma_fork(tmp, mpnt)) goto fail_nomem_anon_vma_fork; tmp->vm_flags &= ~VM_LOCKED; - tmp->vm_mm = mm; tmp->vm_next = tmp->vm_prev = NULL; file = tmp->vm_file; if (file) { diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index d71a987..c7c2aed 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -433,7 +433,8 @@ register_user_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, struct task_struct *tsk) { - return perf_event_create_kernel_counter(attr, -1, tsk->pid, triggered); + return perf_event_create_kernel_counter(attr, -1, task_pid_vnr(tsk), + triggered); } EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 6b5580c..01a0700 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -365,8 +365,6 @@ static unsigned int setup_sgl(struct __kfifo *fifo, struct scatterlist *sgl, n = setup_sgl_buf(sgl, fifo->data + off, nents, l); n += setup_sgl_buf(sgl + n, fifo->data, nents - n, len - l); - if (n) - sg_mark_end(sgl + n - 1); return n; } diff --git a/kernel/module.c b/kernel/module.c index d0b5f8d..ccd6419 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1537,6 +1537,7 @@ static int __unlink_module(void *_mod) { struct module *mod = _mod; list_del(&mod->list); + module_bug_cleanup(mod); return 0; } @@ -2625,6 +2626,7 @@ static struct module *load_module(void __user *umod, if (err < 0) goto ddebug; + module_bug_finalize(info.hdr, info.sechdrs, mod); list_add_rcu(&mod->list, &modules); mutex_unlock(&module_mutex); @@ -2650,6 +2652,8 @@ static struct module *load_module(void __user *umod, mutex_lock(&module_mutex); /* Unlink carefully: kallsyms could be walking list. */ list_del_rcu(&mod->list); + module_bug_cleanup(mod); + ddebug: if (!mod->taints) dynamic_debug_remove(info.debug); diff --git a/kernel/perf_event.c b/kernel/perf_event.c index db5b560..b98bed3 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -2202,15 +2202,13 @@ static void perf_event_for_each(struct perf_event *event, static int perf_event_period(struct perf_event *event, u64 __user *arg) { struct perf_event_context *ctx = event->ctx; - unsigned long size; int ret = 0; u64 value; if (!event->attr.sample_period) return -EINVAL; - size = copy_from_user(&value, arg, sizeof(value)); - if (size != sizeof(value)) + if (copy_from_user(&value, arg, sizeof(value))) return -EFAULT; if (!value) diff --git a/kernel/sched.c b/kernel/sched.c index ed09d4f..dc85ceb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3513,9 +3513,9 @@ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) rtime = nsecs_to_cputime(p->se.sum_exec_runtime); if (total) { - u64 temp; + u64 temp = rtime; - temp = (u64)(rtime * utime); + temp *= utime; do_div(temp, total); utime = (cputime_t)temp; } else @@ -3546,9 +3546,9 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) rtime = nsecs_to_cputime(cputime.sum_exec_runtime); if (total) { - u64 temp; + u64 temp = rtime; - temp = (u64)(rtime * cputime.utime); + temp *= cputime.utime; do_div(temp, total); utime = (cputime_t)temp; } else diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 9b5b4f8..db3f674 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -54,13 +54,13 @@ enum sched_tunable_scaling sysctl_sched_tunable_scaling * Minimal preemption granularity for CPU-bound tasks: * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds) */ -unsigned int sysctl_sched_min_granularity = 2000000ULL; -unsigned int normalized_sysctl_sched_min_granularity = 2000000ULL; +unsigned int sysctl_sched_min_granularity = 750000ULL; +unsigned int normalized_sysctl_sched_min_granularity = 750000ULL; /* * is kept at sysctl_sched_latency / sysctl_sched_min_granularity */ -static unsigned int sched_nr_latency = 3; +static unsigned int sched_nr_latency = 8; /* * After fork, child runs first. If set to 0 (default) then @@ -3630,7 +3630,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu) if (time_before(now, nohz.next_balance)) return 0; - if (!rq->nr_running) + if (rq->idle_at_tick) return 0; first_pick_cpu = atomic_read(&nohz.first_pick_cpu); diff --git a/kernel/signal.c b/kernel/signal.c index bded651..919562c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2215,6 +2215,14 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from) #ifdef __ARCH_SI_TRAPNO err |= __put_user(from->si_trapno, &to->si_trapno); #endif +#ifdef BUS_MCEERR_AO + /* + * Other callers might not initialize the si_lsb field, + * so check explicitely for the right codes here. + */ + if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) + err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); +#endif break; case __SI_CHLD: err |= __put_user(from->si_pid, &to->si_pid); diff --git a/kernel/smp.c b/kernel/smp.c index 75c970c..ed6aacf 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -365,9 +365,10 @@ call: EXPORT_SYMBOL_GPL(smp_call_function_any); /** - * __smp_call_function_single(): Run a function on another CPU + * __smp_call_function_single(): Run a function on a specific CPU * @cpu: The CPU to run on. * @data: Pre-allocated and setup data structure + * @wait: If true, wait until function has completed on specified CPU. * * Like smp_call_function_single(), but allow caller to pass in a * pre-allocated data structure. Useful for embedding @data inside @@ -376,8 +377,10 @@ EXPORT_SYMBOL_GPL(smp_call_function_any); void __smp_call_function_single(int cpu, struct call_single_data *data, int wait) { - csd_lock(data); + unsigned int this_cpu; + unsigned long flags; + this_cpu = get_cpu(); /* * Can deadlock when called with interrupts disabled. * We allow cpu's that are not yet online though, as no one else can @@ -387,7 +390,15 @@ void __smp_call_function_single(int cpu, struct call_single_data *data, WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait && irqs_disabled() && !oops_in_progress); - generic_exec_single(cpu, data, wait); + if (cpu == this_cpu) { + local_irq_save(flags); + data->func(data->info); + local_irq_restore(flags); + } else { + csd_lock(data); + generic_exec_single(cpu, data, wait); + } + put_cpu(); } /** diff --git a/kernel/sysctl.c b/kernel/sysctl.c index f88552c..3a45c22 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2485,7 +2485,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int kbuf[left] = 0; } - for (; left && vleft--; i++, min++, max++, first=0) { + for (; left && vleft--; i++, first = 0) { unsigned long val; if (write) { diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 492197e..bca9637 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -405,7 +405,7 @@ static inline int test_time_stamp(u64 delta) #define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2)) /* Max number of timestamps that can fit on a page */ -#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_STAMP) +#define RB_TIMESTAMPS_PER_PAGE (BUF_PAGE_SIZE / RB_LEN_TIME_EXTEND) int ring_buffer_print_page_header(struct trace_seq *s) { diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 727f24e..f77afd9 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1,19 +1,26 @@ /* - * linux/kernel/workqueue.c + * kernel/workqueue.c - generic async execution with shared worker pool * - * Generic mechanism for defining kernel helper threads for running - * arbitrary tasks in process context. + * Copyright (C) 2002 Ingo Molnar * - * Started by Ingo Molnar, Copyright (C) 2002 + * Derived from the taskqueue/keventd code by: + * David Woodhouse <dwmw2@infradead.org> + * Andrew Morton + * Kai Petzke <wpp@marie.physik.tu-berlin.de> + * Theodore Ts'o <tytso@mit.edu> * - * Derived from the taskqueue/keventd code by: + * Made to use alloc_percpu by Christoph Lameter. * - * David Woodhouse <dwmw2@infradead.org> - * Andrew Morton - * Kai Petzke <wpp@marie.physik.tu-berlin.de> - * Theodore Ts'o <tytso@mit.edu> + * Copyright (C) 2010 SUSE Linux Products GmbH + * Copyright (C) 2010 Tejun Heo <tj@kernel.org> * - * Made to use alloc_percpu by Christoph Lameter. + * This is the generic async execution mechanism. Work items as are + * executed in process context. The worker pool is shared and + * automatically managed. There is one worker pool for each CPU and + * one extra for works which are better served by workers which are + * not bound to any specific CPU. + * + * Please read Documentation/workqueue.txt for details. */ #include <linux/module.h> @@ -72,8 +72,8 @@ static const struct bug_entry *module_find_bug(unsigned long bugaddr) return NULL; } -int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, - struct module *mod) +void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *mod) { char *secstrings; unsigned int i; @@ -97,8 +97,6 @@ int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, * could potentially lead to deadlock and thus be counter-productive. */ list_add(&mod->bug_list, &module_bug_list); - - return 0; } void module_bug_cleanup(struct module *mod) diff --git a/lib/list_sort.c b/lib/list_sort.c index 4b5cb79..a7616fa 100644 --- a/lib/list_sort.c +++ b/lib/list_sort.c @@ -70,7 +70,7 @@ static void merge_and_restore_back_links(void *priv, * element comparison is needed, so the client's cmp() * routine can invoke cond_resched() periodically. */ - (*cmp)(priv, tail, tail); + (*cmp)(priv, tail->next, tail->next); tail->next->prev = tail; tail = tail->next; diff --git a/mm/backing-dev.c b/mm/backing-dev.c index c2bf86f..65d4204 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -30,6 +30,7 @@ EXPORT_SYMBOL_GPL(default_backing_dev_info); struct backing_dev_info noop_backing_dev_info = { .name = "noop", + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; EXPORT_SYMBOL_GPL(noop_backing_dev_info); @@ -243,6 +244,7 @@ static int __init default_bdi_init(void) err = bdi_init(&default_backing_dev_info); if (!err) bdi_register(&default_backing_dev_info, NULL, "default"); + err = bdi_init(&noop_backing_dev_info); return err; } diff --git a/mm/fremap.c b/mm/fremap.c index 46f5dac..ec520c7 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -125,7 +125,6 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, { struct mm_struct *mm = current->mm; struct address_space *mapping; - unsigned long end = start + size; struct vm_area_struct *vma; int err = -EINVAL; int has_write_lock = 0; @@ -142,6 +141,10 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, if (start + size <= start) return err; + /* Does pgoff wrap? */ + if (pgoff + (size >> PAGE_SHIFT) < pgoff) + return err; + /* Can we represent this offset inside this architecture's pte's? */ #if PTE_FILE_MAX_BITS < BITS_PER_LONG if (pgoff + (size >> PAGE_SHIFT) >= (1UL << PTE_FILE_MAX_BITS)) @@ -168,7 +171,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, if (!(vma->vm_flags & VM_CAN_NONLINEAR)) goto out; - if (end <= start || start < vma->vm_start || end > vma->vm_end) + if (start < vma->vm_start || start + size > vma->vm_end) goto out; /* Must set VM_NONLINEAR before any pages are populated. */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index cc5be78..c032738 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2324,11 +2324,8 @@ retry_avoidcopy: * and just make the page writable */ avoidcopy = (page_mapcount(old_page) == 1); if (avoidcopy) { - if (!trylock_page(old_page)) { - if (PageAnon(old_page)) - page_move_anon_rmap(old_page, vma, address); - } else - unlock_page(old_page); + if (PageAnon(old_page)) + page_move_anon_rmap(old_page, vma, address); set_huge_ptep_writable(vma, address, ptep); return 0; } @@ -2404,7 +2401,7 @@ retry_avoidcopy: set_huge_pte_at(mm, address, ptep, make_huge_pte(vma, new_page, 1)); page_remove_rmap(old_page); - hugepage_add_anon_rmap(new_page, vma, address); + hugepage_add_new_anon_rmap(new_page, vma, address); /* Make the old page be freed below */ new_page = old_page; mmu_notifier_invalidate_range_end(mm, @@ -2631,10 +2628,16 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, vma, address); } - if (!pagecache_page) { - page = pte_page(entry); + /* + * hugetlb_cow() requires page locks of pte_page(entry) and + * pagecache_page, so here we need take the former one + * when page != pagecache_page or !pagecache_page. + * Note that locking order is always pagecache_page -> page, + * so no worry about deadlock. + */ + page = pte_page(entry); + if (page != pagecache_page) lock_page(page); - } spin_lock(&mm->page_table_lock); /* Check for a racing update before calling hugetlb_cow */ @@ -2661,9 +2664,8 @@ out_page_table_lock: if (pagecache_page) { unlock_page(pagecache_page); put_page(pagecache_page); - } else { - unlock_page(page); } + unlock_page(page); out_mutex: mutex_unlock(&hugetlb_instantiation_mutex); @@ -712,7 +712,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, if (!ptep) goto out; - if (pte_write(*ptep)) { + if (pte_write(*ptep) || pte_dirty(*ptep)) { pte_t entry; swapped = PageSwapCache(page); @@ -735,7 +735,9 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, set_pte_at(mm, addr, ptep, entry); goto out_unlock; } - entry = pte_wrprotect(entry); + if (pte_dirty(entry)) + set_page_dirty(page); + entry = pte_mkclean(pte_wrprotect(entry)); set_pte_at_notify(mm, addr, ptep, entry); } *orig_pte = *ptep; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3eed583..9be3cf8 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3587,9 +3587,13 @@ unlock: static void mem_cgroup_threshold(struct mem_cgroup *memcg) { - __mem_cgroup_threshold(memcg, false); - if (do_swap_account) - __mem_cgroup_threshold(memcg, true); + while (memcg) { + __mem_cgroup_threshold(memcg, false); + if (do_swap_account) + __mem_cgroup_threshold(memcg, true); + + memcg = parent_mem_cgroup(memcg); + } } static int compare_thresholds(const void *a, const void *b) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 9c26eec..757f6b0 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -183,7 +183,7 @@ EXPORT_SYMBOL_GPL(hwpoison_filter); * signal. */ static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno, - unsigned long pfn) + unsigned long pfn, struct page *page) { struct siginfo si; int ret; @@ -198,7 +198,7 @@ static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno, #ifdef __ARCH_SI_TRAPNO si.si_trapno = trapno; #endif - si.si_addr_lsb = PAGE_SHIFT; + si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT; /* * Don't use force here, it's convenient if the signal * can be temporarily blocked. @@ -235,7 +235,7 @@ void shake_page(struct page *p, int access) int nr; do { nr = shrink_slab(1000, GFP_KERNEL, 1000); - if (page_count(p) == 0) + if (page_count(p) == 1) break; } while (nr > 10); } @@ -327,7 +327,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p, * wrong earlier. */ static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno, - int fail, unsigned long pfn) + int fail, struct page *page, unsigned long pfn) { struct to_kill *tk, *next; @@ -352,7 +352,7 @@ static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno, * process anyways. */ else if (kill_proc_ao(tk->tsk, tk->addr, trapno, - pfn) < 0) + pfn, page) < 0) printk(KERN_ERR "MCE %#lx: Cannot send advisory machine check signal to %s:%d\n", pfn, tk->tsk->comm, tk->tsk->pid); @@ -928,7 +928,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * any accesses to the poisoned memory. */ kill_procs_ao(&tokill, !!PageDirty(hpage), trapno, - ret != SWAP_SUCCESS, pfn); + ret != SWAP_SUCCESS, p, pfn); return ret; } diff --git a/mm/memory.c b/mm/memory.c index 71b161b..0e18b4d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2680,10 +2680,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, delayacct_clear_flag(DELAYACCT_PF_SWAPIN); /* - * Make sure try_to_free_swap didn't release the swapcache - * from under us. The page pin isn't enough to prevent that. + * Make sure try_to_free_swap or reuse_swap_page or swapoff did not + * release the swapcache from under us. The page pin, and pte_same + * test below, are not enough to exclude that. Even if it is still + * swapcache, we need to check that the page's swap has not changed. */ - if (unlikely(!PageSwapCache(page))) + if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val)) goto out_page; if (ksm_might_need_to_copy(page, vma, address)) { @@ -2009,6 +2009,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, removed_exe_file_vma(mm); fput(new->vm_file); } + unlink_anon_vmas(new); out_free_mpol: mpol_put(pol); out_free_vma: diff --git a/mm/oom_kill.c b/mm/oom_kill.c index fc81cb2..4029583 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -121,8 +121,8 @@ struct task_struct *find_lock_task_mm(struct task_struct *p) } /* return true if the task is not adequate as candidate victim task. */ -static bool oom_unkillable_task(struct task_struct *p, struct mem_cgroup *mem, - const nodemask_t *nodemask) +static bool oom_unkillable_task(struct task_struct *p, + const struct mem_cgroup *mem, const nodemask_t *nodemask) { if (is_global_init(p)) return true; @@ -208,8 +208,13 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, */ points += p->signal->oom_score_adj; - if (points < 0) - return 0; + /* + * Never return 0 for an eligible task that may be killed since it's + * possible that no single user task uses more than 0.1% of memory and + * no single admin tasks uses more than 3.0%. + */ + if (points <= 0) + return 1; return (points < 1000) ? points : 1000; } @@ -339,26 +344,24 @@ static struct task_struct *select_bad_process(unsigned int *ppoints, /** * dump_tasks - dump current memory state of all system tasks * @mem: current's memory controller, if constrained + * @nodemask: nodemask passed to page allocator for mempolicy ooms * - * Dumps the current memory state of all system tasks, excluding kernel threads. + * Dumps the current memory state of all eligible tasks. Tasks not in the same + * memcg, not in the same cpuset, or bound to a disjoint set of mempolicy nodes + * are not shown. * State information includes task's pid, uid, tgid, vm size, rss, cpu, oom_adj * value, oom_score_adj value, and name. * - * If the actual is non-NULL, only tasks that are a member of the mem_cgroup are - * shown. - * * Call with tasklist_lock read-locked. */ -static void dump_tasks(const struct mem_cgroup *mem) +static void dump_tasks(const struct mem_cgroup *mem, const nodemask_t *nodemask) { struct task_struct *p; struct task_struct *task; pr_info("[ pid ] uid tgid total_vm rss cpu oom_adj oom_score_adj name\n"); for_each_process(p) { - if (p->flags & PF_KTHREAD) - continue; - if (mem && !task_in_mem_cgroup(p, mem)) + if (oom_unkillable_task(p, mem, nodemask)) continue; task = find_lock_task_mm(p); @@ -381,7 +384,7 @@ static void dump_tasks(const struct mem_cgroup *mem) } static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, - struct mem_cgroup *mem) + struct mem_cgroup *mem, const nodemask_t *nodemask) { task_lock(current); pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, " @@ -394,7 +397,7 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, mem_cgroup_print_oom_info(mem, p); show_mem(); if (sysctl_oom_dump_tasks) - dump_tasks(mem); + dump_tasks(mem, nodemask); } #define K(x) ((x) << (PAGE_SHIFT-10)) @@ -436,7 +439,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, unsigned int victim_points = 0; if (printk_ratelimit()) - dump_header(p, gfp_mask, order, mem); + dump_header(p, gfp_mask, order, mem, nodemask); /* * If the task is already exiting, don't alarm the sysadmin or kill @@ -482,7 +485,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, * Determines whether the kernel must panic because of the panic_on_oom sysctl. */ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, - int order) + int order, const nodemask_t *nodemask) { if (likely(!sysctl_panic_on_oom)) return; @@ -496,7 +499,7 @@ static void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask, return; } read_lock(&tasklist_lock); - dump_header(NULL, gfp_mask, order, NULL); + dump_header(NULL, gfp_mask, order, NULL, nodemask); read_unlock(&tasklist_lock); panic("Out of memory: %s panic_on_oom is enabled\n", sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); @@ -509,7 +512,7 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask) unsigned int points = 0; struct task_struct *p; - check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0); + check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL); limit = mem_cgroup_get_limit(mem) >> PAGE_SHIFT; read_lock(&tasklist_lock); retry: @@ -641,6 +644,7 @@ static void clear_system_oom(void) void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order, nodemask_t *nodemask) { + const nodemask_t *mpol_mask; struct task_struct *p; unsigned long totalpages; unsigned long freed = 0; @@ -670,7 +674,8 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, */ constraint = constrained_alloc(zonelist, gfp_mask, nodemask, &totalpages); - check_panic_on_oom(constraint, gfp_mask, order); + mpol_mask = (constraint == CONSTRAINT_MEMORY_POLICY) ? nodemask : NULL; + check_panic_on_oom(constraint, gfp_mask, order, mpol_mask); read_lock(&tasklist_lock); if (sysctl_oom_kill_allocating_task && @@ -688,15 +693,13 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, } retry: - p = select_bad_process(&points, totalpages, NULL, - constraint == CONSTRAINT_MEMORY_POLICY ? nodemask : - NULL); + p = select_bad_process(&points, totalpages, NULL, mpol_mask); if (PTR_ERR(p) == -1UL) goto out; /* Found nothing?!?! Either we hang forever, or we panic. */ if (!p) { - dump_header(NULL, gfp_mask, order, NULL); + dump_header(NULL, gfp_mask, order, NULL, mpol_mask); read_unlock(&tasklist_lock); panic("Out of memory and no killable processes...\n"); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a8cfa9c..f12ad18 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5182,9 +5182,9 @@ void *__init alloc_large_system_hash(const char *tablename, if (!table) panic("Failed to allocate %s hash table\n", tablename); - printk(KERN_INFO "%s hash table entries: %d (order: %d, %lu bytes)\n", + printk(KERN_INFO "%s hash table entries: %ld (order: %d, %lu bytes)\n", tablename, - (1U << log2qty), + (1UL << log2qty), ilog2(size) - PAGE_SHIFT, size); diff --git a/mm/percpu.c b/mm/percpu.c index 58c572b..c76ef38 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1401,9 +1401,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, if (pcpu_first_unit_cpu == NR_CPUS) pcpu_first_unit_cpu = cpu; + pcpu_last_unit_cpu = cpu; } } - pcpu_last_unit_cpu = cpu; pcpu_nr_units = unit; for_each_possible_cpu(cpu) @@ -381,7 +381,13 @@ vma_address(struct page *page, struct vm_area_struct *vma) unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) { if (PageAnon(page)) { - if (vma->anon_vma->root != page_anon_vma(page)->root) + struct anon_vma *page__anon_vma = page_anon_vma(page); + /* + * Note: swapoff's unuse_vma() is more efficient with this + * check, and needs it to match anon_vma when KSM is active. + */ + if (!vma->anon_vma || !page__anon_vma || + vma->anon_vma->root != page__anon_vma->root) return -EFAULT; } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) { if (!vma->vm_file || @@ -1564,13 +1570,14 @@ static void __hugepage_set_anon_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address, int exclusive) { struct anon_vma *anon_vma = vma->anon_vma; + BUG_ON(!anon_vma); - if (!exclusive) { - struct anon_vma_chain *avc; - avc = list_entry(vma->anon_vma_chain.prev, - struct anon_vma_chain, same_vma); - anon_vma = avc->anon_vma; - } + + if (PageAnon(page)) + return; + if (!exclusive) + anon_vma = anon_vma->root; + anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; page->mapping = (struct address_space *) anon_vma; page->index = linear_page_index(vma, address); @@ -1581,6 +1588,8 @@ void hugepage_add_anon_rmap(struct page *page, { struct anon_vma *anon_vma = vma->anon_vma; int first; + + BUG_ON(!PageLocked(page)); BUG_ON(!anon_vma); BUG_ON(address < vma->vm_start || address >= vma->vm_end); first = atomic_inc_and_test(&page->_mapcount); diff --git a/mm/vmscan.c b/mm/vmscan.c index c391c32..c5dfabf 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1804,12 +1804,11 @@ static void shrink_zone(int priority, struct zone *zone, * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ -static bool shrink_zones(int priority, struct zonelist *zonelist, +static void shrink_zones(int priority, struct zonelist *zonelist, struct scan_control *sc) { struct zoneref *z; struct zone *zone; - bool all_unreclaimable = true; for_each_zone_zonelist_nodemask(zone, z, zonelist, gfp_zone(sc->gfp_mask), sc->nodemask) { @@ -1827,8 +1826,38 @@ static bool shrink_zones(int priority, struct zonelist *zonelist, } shrink_zone(priority, zone, sc); - all_unreclaimable = false; } +} + +static bool zone_reclaimable(struct zone *zone) +{ + return zone->pages_scanned < zone_reclaimable_pages(zone) * 6; +} + +/* + * As hibernation is going on, kswapd is freezed so that it can't mark + * the zone into all_unreclaimable. It can't handle OOM during hibernation. + * So let's check zone's unreclaimable in direct reclaim as well as kswapd. + */ +static bool all_unreclaimable(struct zonelist *zonelist, + struct scan_control *sc) +{ + struct zoneref *z; + struct zone *zone; + bool all_unreclaimable = true; + + for_each_zone_zonelist_nodemask(zone, z, zonelist, + gfp_zone(sc->gfp_mask), sc->nodemask) { + if (!populated_zone(zone)) + continue; + if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) + continue; + if (zone_reclaimable(zone)) { + all_unreclaimable = false; + break; + } + } + return all_unreclaimable; } @@ -1852,7 +1881,6 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, struct scan_control *sc) { int priority; - bool all_unreclaimable; unsigned long total_scanned = 0; struct reclaim_state *reclaim_state = current->reclaim_state; struct zoneref *z; @@ -1869,7 +1897,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, sc->nr_scanned = 0; if (!priority) disable_swap_token(); - all_unreclaimable = shrink_zones(priority, zonelist, sc); + shrink_zones(priority, zonelist, sc); /* * Don't shrink slabs when reclaiming memory from * over limit cgroups @@ -1931,7 +1959,7 @@ out: return sc->nr_reclaimed; /* top priority shrink_zones still had more to do? don't OOM, then */ - if (scanning_global_lru(sc) && !all_unreclaimable) + if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc)) return 1; return 0; @@ -2197,8 +2225,7 @@ loop_again: total_scanned += sc.nr_scanned; if (zone->all_unreclaimable) continue; - if (nr_slab == 0 && - zone->pages_scanned >= (zone_reclaimable_pages(zone) * 6)) + if (nr_slab == 0 && !zone_reclaimable(zone)) zone->all_unreclaimable = 1; /* * If we've done a decent amount of scanning and diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 01ddb04..0eb96f7 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -24,8 +24,11 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, if (vlan_dev) skb->dev = vlan_dev; - else if (vlan_id) - goto drop; + else if (vlan_id) { + if (!(skb->dev->flags & IFF_PROMISC)) + goto drop; + skb->pkt_type = PACKET_OTHERHOST; + } return (polling ? netif_receive_skb(skb) : netif_rx(skb)); @@ -102,8 +105,11 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, if (vlan_dev) skb->dev = vlan_dev; - else if (vlan_id) - goto drop; + else if (vlan_id) { + if (!(skb->dev->flags & IFF_PROMISC)) + goto drop; + skb->pkt_type = PACKET_OTHERHOST; + } for (p = napi->gro_list; p; p = p->next) { NAPI_GRO_CB(p)->same_flow = diff --git a/net/9p/client.c b/net/9p/client.c index dc6f2f2..9eb7250 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -331,8 +331,10 @@ static void p9_tag_cleanup(struct p9_client *c) } } - if (c->tagpool) + if (c->tagpool) { + p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */ p9_idpool_destroy(c->tagpool); + } /* free requests associated with tags */ for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { @@ -944,6 +946,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, int16_t nwqids, count; err = 0; + wqids = NULL; clnt = oldfid->clnt; if (clone) { fid = p9_fid_create(clnt); @@ -994,9 +997,11 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, else fid->qid = oldfid->qid; + kfree(wqids); return fid; clunk_fid: + kfree(wqids); p9_client_clunk(fid); fid = NULL; diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 0ea20c3..17c5ba7 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -426,8 +426,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) /* Allocate an fcall for the reply */ rpl_context = kmalloc(sizeof *rpl_context, GFP_KERNEL); - if (!rpl_context) + if (!rpl_context) { + err = -ENOMEM; goto err_close; + } /* * If the request has a buffer, steal it, otherwise @@ -445,8 +447,8 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) } rpl_context->rc = req->rc; if (!rpl_context->rc) { - kfree(rpl_context); - goto err_close; + err = -ENOMEM; + goto err_free2; } /* @@ -458,11 +460,8 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) */ if (atomic_inc_return(&rdma->rq_count) <= rdma->rq_depth) { err = post_recv(client, rpl_context); - if (err) { - kfree(rpl_context->rc); - kfree(rpl_context); - goto err_close; - } + if (err) + goto err_free1; } else atomic_dec(&rdma->rq_count); @@ -471,8 +470,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) /* Post the request */ c = kmalloc(sizeof *c, GFP_KERNEL); - if (!c) - goto err_close; + if (!c) { + err = -ENOMEM; + goto err_free1; + } c->req = req; c->busa = ib_dma_map_single(rdma->cm_id->device, @@ -499,9 +500,15 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) return ib_post_send(rdma->qp, &wr, &bad_wr); error: + kfree(c); + kfree(rpl_context->rc); + kfree(rpl_context); P9_DPRINTK(P9_DEBUG_ERROR, "EIO\n"); return -EIO; - + err_free1: + kfree(rpl_context->rc); + err_free2: + kfree(rpl_context); err_close: spin_lock_irqsave(&rdma->req_lock, flags); if (rdma->state < P9_RDMA_CLOSING) { diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index dcfbe99..b885159 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -329,7 +329,8 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) mutex_lock(&virtio_9p_lock); list_for_each_entry(chan, &virtio_chan_list, chan_list) { - if (!strncmp(devname, chan->tag, chan->tag_len)) { + if (!strncmp(devname, chan->tag, chan->tag_len) && + strlen(devname) == chan->tag_len) { if (!chan->inuse) { chan->inuse = true; found = 1; diff --git a/net/Kconfig b/net/Kconfig index e330594..e926884 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -217,7 +217,7 @@ source "net/dns_resolver/Kconfig" config RPS boolean - depends on SMP && SYSFS + depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS default y menu "Network testing" diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 651babd..ad2b232 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -399,12 +399,6 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) unregister_netdev(net_dev); free_netdev(net_dev); } - read_lock_irq(&devs_lock); - if (list_empty(&br2684_devs)) { - /* last br2684 device */ - unregister_atmdevice_notifier(&atm_dev_notifier); - } - read_unlock_irq(&devs_lock); return; } @@ -675,7 +669,6 @@ static int br2684_create(void __user *arg) if (list_empty(&br2684_devs)) { /* 1st br2684 device */ - register_atmdevice_notifier(&atm_dev_notifier); brdev->number = 1; } else brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1; @@ -815,6 +808,7 @@ static int __init br2684_init(void) return -ENOMEM; #endif register_atm_ioctl(&br2684_ioctl_ops); + register_atmdevice_notifier(&atm_dev_notifier); return 0; } @@ -830,9 +824,7 @@ static void __exit br2684_exit(void) #endif - /* if not already empty */ - if (!list_empty(&br2684_devs)) - unregister_atmdevice_notifier(&atm_dev_notifier); + unregister_atmdevice_notifier(&atm_dev_notifier); while (!list_empty(&br2684_devs)) { net_dev = list_entry_brdev(br2684_devs.next); diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 622b471..74bcc66 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -778,7 +778,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) eg->packets_rcvd++; mpc->eg_ops->put(eg); - memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); + memset(ATM_SKB(new_skb), 0, sizeof(struct atm_skb_data)); netif_rx(new_skb); } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index fadf26b..0b54b7d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1441,33 +1441,23 @@ static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb) static void l2cap_streaming_send(struct sock *sk) { - struct sk_buff *skb, *tx_skb; + struct sk_buff *skb; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; - while ((skb = sk->sk_send_head)) { - tx_skb = skb_clone(skb, GFP_ATOMIC); - - control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); + while ((skb = skb_dequeue(TX_QUEUE(sk)))) { + control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE); control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; - put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); + put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE); if (pi->fcs == L2CAP_FCS_CRC16) { - fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); - put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); + fcs = crc16(0, (u8 *)skb->data, skb->len - 2); + put_unaligned_le16(fcs, skb->data + skb->len - 2); } - l2cap_do_send(sk, tx_skb); + l2cap_do_send(sk, skb); pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; - - if (skb_queue_is_last(TX_QUEUE(sk), skb)) - sk->sk_send_head = NULL; - else - sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); - - skb = skb_dequeue(TX_QUEUE(sk)); - kfree_skb(skb); } } @@ -1960,6 +1950,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us switch (optname) { case L2CAP_OPTIONS: + if (sk->sk_state == BT_CONNECTED) { + err = -EINVAL; + break; + } + opts.imtu = l2cap_pi(sk)->imtu; opts.omtu = l2cap_pi(sk)->omtu; opts.flush_to = l2cap_pi(sk)->flush_to; @@ -2771,10 +2766,10 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, case L2CAP_CONF_MTU: if (val < L2CAP_DEFAULT_MIN_MTU) { *result = L2CAP_CONF_UNACCEPT; - pi->omtu = L2CAP_DEFAULT_MIN_MTU; + pi->imtu = L2CAP_DEFAULT_MIN_MTU; } else - pi->omtu = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); + pi->imtu = val; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); break; case L2CAP_CONF_FLUSH_TO: @@ -3071,6 +3066,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd return 0; } +static inline void set_default_fcs(struct l2cap_pinfo *pi) +{ + /* FCS is enabled only in ERTM or streaming mode, if one or both + * sides request it. + */ + if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) + pi->fcs = L2CAP_FCS_NONE; + else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV)) + pi->fcs = L2CAP_FCS_CRC16; +} + static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) { struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; @@ -3088,14 +3094,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (!sk) return -ENOENT; - if (sk->sk_state != BT_CONFIG) { - struct l2cap_cmd_rej rej; - - rej.reason = cpu_to_le16(0x0002); - l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, - sizeof(rej), &rej); + if (sk->sk_state == BT_DISCONN) goto unlock; - } /* Reject if config buffer is too small. */ len = cmd_len - sizeof(*req); @@ -3135,9 +3135,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr goto unlock; if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) || - l2cap_pi(sk)->fcs != L2CAP_FCS_NONE) - l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16; + set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; @@ -3225,9 +3223,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { - if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_NO_FCS_RECV) || - l2cap_pi(sk)->fcs != L2CAP_FCS_NONE) - l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16; + set_default_fcs(l2cap_pi(sk)); sk->sk_state = BT_CONNECTED; l2cap_pi(sk)->next_tx_seq = 0; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 44a6232..194b3a0 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -82,11 +82,14 @@ static void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb) static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) { struct sock *sk = d->owner, *parent; + unsigned long flags; + if (!sk) return; BT_DBG("dlc %p state %ld err %d", d, d->state, err); + local_irq_save(flags); bh_lock_sock(sk); if (err) @@ -108,6 +111,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) } bh_unlock_sock(sk); + local_irq_restore(flags); if (parent && sock_flag(sk, SOCK_ZAPPED)) { /* We have to drop DLC lock here, otherwise diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 8ce9047..4bf28f2 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -827,6 +827,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, long timeo; int err; int ifindex, headroom, tailroom; + unsigned int mtu; struct net_device *dev; lock_sock(sk); @@ -896,15 +897,23 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, cf_sk->sk.sk_state = CAIF_DISCONNECTED; goto out; } - dev = dev_get_by_index(sock_net(sk), ifindex); + + err = -ENODEV; + rcu_read_lock(); + dev = dev_get_by_index_rcu(sock_net(sk), ifindex); + if (!dev) { + rcu_read_unlock(); + goto out; + } cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom); + mtu = dev->mtu; + rcu_read_unlock(); + cf_sk->tailroom = tailroom; - cf_sk->maxframe = dev->mtu - (headroom + tailroom); - dev_put(dev); + cf_sk->maxframe = mtu - (headroom + tailroom); if (cf_sk->maxframe < 1) { - pr_warning("CAIF: %s(): CAIF Interface MTU too small (%d)\n", - __func__, dev->mtu); - err = -ENODEV; + pr_warning("CAIF: %s(): CAIF Interface MTU too small (%u)\n", + __func__, mtu); goto out; } diff --git a/net/core/dev.c b/net/core/dev.c index b9b22a3..660dd41 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4845,7 +4845,7 @@ static void rollback_registered_many(struct list_head *head) dev = list_first_entry(head, struct net_device, unreg_list); call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); - synchronize_net(); + rcu_barrier(); list_for_each_entry(dev, head, unreg_list) dev_put(dev); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 7a85367..8451ab4 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -348,7 +348,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, if (info.cmd == ETHTOOL_GRXCLSRLALL) { if (info.rule_cnt > 0) { if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32)) - rule_buf = kmalloc(info.rule_cnt * sizeof(u32), + rule_buf = kzalloc(info.rule_cnt * sizeof(u32), GFP_USER); if (!rule_buf) return -ENOMEM; @@ -397,7 +397,7 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev, (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index)) return -ENOMEM; full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size; - indir = kmalloc(full_size, GFP_USER); + indir = kzalloc(full_size, GFP_USER); if (!indir) return -ENOMEM; @@ -538,7 +538,7 @@ static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) gstrings.len = ret; - data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); + data = kzalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); if (!data) return -ENOMEM; @@ -775,7 +775,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) if (regs.len > reglen) regs.len = reglen; - regbuf = kmalloc(reglen, GFP_USER); + regbuf = kzalloc(reglen, GFP_USER); if (!regbuf) return -ENOMEM; diff --git a/net/core/iovec.c b/net/core/iovec.c index 1cd98df..e6b133b 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -35,9 +35,10 @@ * in any case. */ -int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode) +long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode) { - int size, err, ct; + int size, ct; + long err; if (m->msg_namelen) { if (mode == VERIFY_READ) { diff --git a/net/core/sock.c b/net/core/sock.c index b05b9b6..ef30e9d 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1351,9 +1351,9 @@ int sock_i_uid(struct sock *sk) { int uid; - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0; - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); return uid; } EXPORT_SYMBOL(sock_i_uid); @@ -1362,9 +1362,9 @@ unsigned long sock_i_ino(struct sock *sk) { unsigned long ino; - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); return ino; } EXPORT_SYMBOL(sock_i_ino); diff --git a/net/core/stream.c b/net/core/stream.c index d959e0f..f5df85d 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -141,10 +141,10 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); sk->sk_write_pending++; - sk_wait_event(sk, ¤t_timeo, !sk->sk_err && - !(sk->sk_shutdown & SEND_SHUTDOWN) && - sk_stream_memory_free(sk) && - vm_wait); + sk_wait_event(sk, ¤t_timeo, sk->sk_err || + (sk->sk_shutdown & SEND_SHUTDOWN) || + (sk_stream_memory_free(sk) && + !vm_wait)); sk->sk_write_pending--; if (vm_wait) { diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 571f895..7cd7760 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -217,6 +217,7 @@ config NET_IPIP config NET_IPGRE tristate "IP: GRE tunnels over IP" + depends on IPV6 || IPV6=n help Tunneling means encapsulating data of one protocol type within another protocol and sending it over a channel that understands the @@ -412,7 +413,7 @@ config INET_XFRM_MODE_BEET If unsure, say Y. config INET_LRO - bool "Large Receive Offload (ipv4/tcp)" + tristate "Large Receive Offload (ipv4/tcp)" default y ---help--- Support for Large Receive Offload (ipv4/tcp). diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index a1ad0e7..2a4bb76 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -856,6 +856,18 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, igmpv3_clear_delrec(in_dev); } else if (len < 12) { return; /* ignore bogus packet; freed by caller */ + } else if (IGMP_V1_SEEN(in_dev)) { + /* This is a v3 query with v1 queriers present */ + max_delay = IGMP_Query_Response_Interval; + group = 0; + } else if (IGMP_V2_SEEN(in_dev)) { + /* this is a v3 query with v2 queriers present; + * Interpretation of the max_delay code is problematic here. + * A real v2 host would use ih_code directly, while v3 has a + * different encoding. We use the v3 encoding as more likely + * to be intended in a v3 query. + */ + max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); } else { /* v3 */ if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) return; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 945b20a..35c93e8 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -45,7 +45,7 @@ #include <net/netns/generic.h> #include <net/rtnetlink.h> -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include <net/ipv6.h> #include <net/ip6_fib.h> #include <net/ip6_route.h> @@ -699,7 +699,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev if ((dst = rt->rt_gateway) == 0) goto tx_error_icmp; } -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) { struct in6_addr *addr6; int addr_type; @@ -774,7 +774,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev goto tx_error; } } -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) { struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); @@ -850,7 +850,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev if ((iph->ttl = tiph->ttl) == 0) { if (skb->protocol == htons(ETH_P_IP)) iph->ttl = old_iph->ttl; -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit; #endif diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 04b6989..7649d77 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -488,9 +488,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) * we can switch to copy when see the first bad fragment. */ if (skb_has_frags(skb)) { - struct sk_buff *frag; + struct sk_buff *frag, *frag2; int first_len = skb_pagelen(skb); - int truesizes = 0; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -503,18 +502,18 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (frag->len > mtu || ((frag->len & 7) && frag->next) || skb_headroom(frag) < hlen) - goto slow_path; + goto slow_path_clean; /* Partially cloned skb? */ if (skb_shared(frag)) - goto slow_path; + goto slow_path_clean; BUG_ON(frag->sk); if (skb->sk) { frag->sk = skb->sk; frag->destructor = sock_wfree; } - truesizes += frag->truesize; + skb->truesize -= frag->truesize; } /* Everything is OK. Generate! */ @@ -524,7 +523,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) frag = skb_shinfo(skb)->frag_list; skb_frag_list_init(skb); skb->data_len = first_len - skb_headlen(skb); - skb->truesize -= truesizes; skb->len = first_len; iph->tot_len = htons(first_len); iph->frag_off = htons(IP_MF); @@ -576,6 +574,15 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) } IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS); return err; + +slow_path_clean: + skb_walk_frags(skb, frag2) { + if (frag2 == frag) + break; + frag2->sk = NULL; + frag2->destructor = NULL; + skb->truesize += frag2->truesize; + } } slow_path: diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 6c40a8c..64b70ad 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -1129,6 +1129,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, case IP_HDRINCL: val = inet->hdrincl; break; + case IP_NODEFRAG: + val = inet->nodefrag; + break; case IP_MTU_DISCOVER: val = inet->pmtudisc; break; diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index b254daf..43eec80 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -112,6 +112,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) /* ip_route_me_harder expects skb->dst to be set */ skb_dst_set_noref(nskb, skb_dst(oldskb)); + nskb->protocol = htons(ETH_P_IP); if (ip_route_me_harder(nskb, addr_type)) goto free_nskb; diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index eab8de3..f3a9b42 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -66,9 +66,11 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { + struct sock *sk = skb->sk; struct inet_sock *inet = inet_sk(skb->sk); - if (inet && inet->nodefrag) + if (sk && (sk->sk_family == PF_INET) && + inet->nodefrag) return NF_ACCEPT; #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 1679e2c..ee5f419 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -893,13 +893,15 @@ static void fast_csum(__sum16 *csum, unsigned char s[4]; if (offset & 1) { - s[0] = s[2] = 0; + s[0] = ~0; s[1] = ~*optr; + s[2] = 0; s[3] = *nptr; } else { - s[1] = s[3] = 0; s[0] = ~*optr; + s[1] = ~0; s[2] = *nptr; + s[3] = 0; } *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum))); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6298f75..ac6559c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1231,7 +1231,7 @@ restart: } if (net_ratelimit()) - printk(KERN_WARNING "Neighbour table overflow.\n"); + printk(KERN_WARNING "ipv4: Neighbour table overflow.\n"); rt_drop(rt); return -ENOBUFS; } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 3fb1428..f115ea6 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -386,8 +386,6 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) */ mask = 0; - if (sk->sk_err) - mask = POLLERR; /* * POLLHUP is certainly not done right. But poll() doesn't @@ -457,6 +455,11 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) if (tp->urg_data & TCP_URG_VALID) mask |= POLLPRI; } + /* This barrier is coupled with smp_wmb() in tcp_reset() */ + smp_rmb(); + if (sk->sk_err) + mask |= POLLERR; + return mask; } EXPORT_SYMBOL(tcp_poll); @@ -940,7 +943,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sg = sk->sk_route_caps & NETIF_F_SG; while (--iovlen >= 0) { - int seglen = iov->iov_len; + size_t seglen = iov->iov_len; unsigned char __user *from = iov->iov_base; iov++; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e663b78..b55f60f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2545,7 +2545,8 @@ static void tcp_mark_head_lost(struct sock *sk, int packets) cnt += tcp_skb_pcount(skb); if (cnt > packets) { - if (tcp_is_sack(tp) || (oldcnt >= packets)) + if ((tcp_is_sack(tp) && !tcp_is_fack(tp)) || + (oldcnt >= packets)) break; mss = skb_shinfo(skb)->gso_size; @@ -4048,6 +4049,8 @@ static void tcp_reset(struct sock *sk) default: sk->sk_err = ECONNRESET; } + /* This barrier is coupled with smp_rmb() in tcp_poll() */ + smp_wmb(); if (!sock_flag(sk, SOCK_DEAD)) sk->sk_error_report(sk); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c35b469..74c54b3 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -135,13 +135,16 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) /* This function calculates a "timeout" which is equivalent to the timeout of a * TCP connection after "boundary" unsuccessful, exponentially backed-off - * retransmissions with an initial RTO of TCP_RTO_MIN. + * retransmissions with an initial RTO of TCP_RTO_MIN or TCP_TIMEOUT_INIT if + * syn_set flag is set. */ static bool retransmits_timed_out(struct sock *sk, - unsigned int boundary) + unsigned int boundary, + bool syn_set) { unsigned int timeout, linear_backoff_thresh; unsigned int start_ts; + unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN; if (!inet_csk(sk)->icsk_retransmits) return false; @@ -151,12 +154,12 @@ static bool retransmits_timed_out(struct sock *sk, else start_ts = tcp_sk(sk)->retrans_stamp; - linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); + linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base); if (boundary <= linear_backoff_thresh) - timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; + timeout = ((2 << boundary) - 1) * rto_base; else - timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + + timeout = ((2 << linear_backoff_thresh) - 1) * rto_base + (boundary - linear_backoff_thresh) * TCP_RTO_MAX; return (tcp_time_stamp - start_ts) >= timeout; @@ -167,14 +170,15 @@ static int tcp_write_timeout(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); int retry_until; - bool do_reset; + bool do_reset, syn_set = 0; if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { if (icsk->icsk_retransmits) dst_negative_advice(sk); retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; + syn_set = 1; } else { - if (retransmits_timed_out(sk, sysctl_tcp_retries1)) { + if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0)) { /* Black hole detection */ tcp_mtu_probing(icsk, sk); @@ -187,14 +191,14 @@ static int tcp_write_timeout(struct sock *sk) retry_until = tcp_orphan_retries(sk, alive); do_reset = alive || - !retransmits_timed_out(sk, retry_until); + !retransmits_timed_out(sk, retry_until, 0); if (tcp_out_of_resources(sk, do_reset)) return 1; } } - if (retransmits_timed_out(sk, retry_until)) { + if (retransmits_timed_out(sk, retry_until, syn_set)) { /* Has it gone just too far? */ tcp_write_err(sk); return 1; @@ -436,7 +440,7 @@ out_reset_timer: icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); } inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); - if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1)) + if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0)) __sk_dst_reset(sk); out:; diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 869078d..a580349 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -61,7 +61,7 @@ static int xfrm4_get_saddr(struct net *net, static int xfrm4_get_tos(struct flowi *fl) { - return fl->fl4_tos; + return IPTOS_RT_MASK & fl->fl4_tos; /* Strip ECN bits */ } static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst, diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 1ef1366..4794762 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -21,21 +21,25 @@ static int xfrm4_init_flags(struct xfrm_state *x) } static void -__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, - struct xfrm_tmpl *tmpl, - xfrm_address_t *daddr, xfrm_address_t *saddr) +__xfrm4_init_tempsel(struct xfrm_selector *sel, struct flowi *fl) +{ + sel->daddr.a4 = fl->fl4_dst; + sel->saddr.a4 = fl->fl4_src; + sel->dport = xfrm_flowi_dport(fl); + sel->dport_mask = htons(0xffff); + sel->sport = xfrm_flowi_sport(fl); + sel->sport_mask = htons(0xffff); + sel->family = AF_INET; + sel->prefixlen_d = 32; + sel->prefixlen_s = 32; + sel->proto = fl->proto; + sel->ifindex = fl->oif; +} + +static void +xfrm4_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl, + xfrm_address_t *daddr, xfrm_address_t *saddr) { - x->sel.daddr.a4 = fl->fl4_dst; - x->sel.saddr.a4 = fl->fl4_src; - x->sel.dport = xfrm_flowi_dport(fl); - x->sel.dport_mask = htons(0xffff); - x->sel.sport = xfrm_flowi_sport(fl); - x->sel.sport_mask = htons(0xffff); - x->sel.family = AF_INET; - x->sel.prefixlen_d = 32; - x->sel.prefixlen_s = 32; - x->sel.proto = fl->proto; - x->sel.ifindex = fl->oif; x->id = tmpl->id; if (x->id.daddr.a4 == 0) x->id.daddr.a4 = daddr->a4; @@ -70,6 +74,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { .owner = THIS_MODULE, .init_flags = xfrm4_init_flags, .init_tempsel = __xfrm4_init_tempsel, + .init_temprop = xfrm4_init_temprop, .output = xfrm4_output, .extract_input = xfrm4_extract_input, .extract_output = xfrm4_extract_output, diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ab70a3f..324fac3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4637,10 +4637,12 @@ int __init addrconf_init(void) if (err < 0) { printk(KERN_CRIT "IPv6 Addrconf:" " cannot initialize default policy table: %d.\n", err); - return err; + goto out; } - register_pernet_subsys(&addrconf_ops); + err = register_pernet_subsys(&addrconf_ops); + if (err < 0) + goto out_addrlabel; /* The addrconf netdev notifier requires that loopback_dev * has it's ipv6 private information allocated and setup @@ -4692,7 +4694,9 @@ errout: unregister_netdevice_notifier(&ipv6_dev_notf); errlo: unregister_pernet_subsys(&addrconf_ops); - +out_addrlabel: + ipv6_addr_label_cleanup(); +out: return err; } @@ -4703,6 +4707,7 @@ void addrconf_cleanup(void) unregister_netdevice_notifier(&ipv6_dev_notf); unregister_pernet_subsys(&addrconf_ops); + ipv6_addr_label_cleanup(); rtnl_lock(); diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index f0e774c..8175f80 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c @@ -393,6 +393,11 @@ int __init ipv6_addr_label_init(void) return register_pernet_subsys(&ipv6_addr_label_ops); } +void ipv6_addr_label_cleanup(void) +{ + unregister_pernet_subsys(&ipv6_addr_label_ops); +} + static const struct nla_policy ifal_policy[IFAL_MAX+1] = { [IFAL_ADDRESS] = { .len = sizeof(struct in6_addr), }, [IFAL_LABEL] = { .len = sizeof(u32), }, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d40b330..980912e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -639,7 +639,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (skb_has_frags(skb)) { int first_len = skb_pagelen(skb); - int truesizes = 0; + struct sk_buff *frag2; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -651,18 +651,18 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (frag->len > mtu || ((frag->len & 7) && frag->next) || skb_headroom(frag) < hlen) - goto slow_path; + goto slow_path_clean; /* Partially cloned skb? */ if (skb_shared(frag)) - goto slow_path; + goto slow_path_clean; BUG_ON(frag->sk); if (skb->sk) { frag->sk = skb->sk; frag->destructor = sock_wfree; - truesizes += frag->truesize; } + skb->truesize -= frag->truesize; } err = 0; @@ -693,7 +693,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) first_len = skb_pagelen(skb); skb->data_len = first_len - skb_headlen(skb); - skb->truesize -= truesizes; skb->len = first_len; ipv6_hdr(skb)->payload_len = htons(first_len - sizeof(struct ipv6hdr)); @@ -756,6 +755,15 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) IPSTATS_MIB_FRAGFAILS); dst_release(&rt->dst); return err; + +slow_path_clean: + skb_walk_frags(skb, frag2) { + if (frag2 == frag) + break; + frag2->sk = NULL; + frag2->destructor = NULL; + skb->truesize += frag2->truesize; + } } slow_path: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d126365..a275c6e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -670,7 +670,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad if (net_ratelimit()) printk(KERN_WARNING - "Neighbour table overflow.\n"); + "ipv6: Neighbour table overflow.\n"); dst_free(&rt->dst); return NULL; } @@ -1556,14 +1556,13 @@ out: * i.e. Path MTU discovery */ -void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, - struct net_device *dev, u32 pmtu) +static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr, + struct net *net, u32 pmtu, int ifindex) { struct rt6_info *rt, *nrt; - struct net *net = dev_net(dev); int allfrag = 0; - rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0); + rt = rt6_lookup(net, daddr, saddr, ifindex, 0); if (rt == NULL) return; @@ -1631,6 +1630,27 @@ out: dst_release(&rt->dst); } +void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, + struct net_device *dev, u32 pmtu) +{ + struct net *net = dev_net(dev); + + /* + * RFC 1981 states that a node "MUST reduce the size of the packets it + * is sending along the path" that caused the Packet Too Big message. + * Since it's not possible in the general case to determine which + * interface was used to send the original packet, we update the MTU + * on the interface that will be used to send future packets. We also + * update the MTU on the interface that received the Packet Too Big in + * case the original packet was forced out that interface with + * SO_BINDTODEVICE or similar. This is the next best thing to the + * correct behaviour, which would be to update the MTU on all + * interfaces. + */ + rt6_do_pmtu_disc(daddr, saddr, net, pmtu, 0); + rt6_do_pmtu_disc(daddr, saddr, net, pmtu, dev->ifindex); +} + /* * Misc support functions */ diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index f417b77..a67575d 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -20,23 +20,27 @@ #include <net/addrconf.h> static void -__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, - struct xfrm_tmpl *tmpl, - xfrm_address_t *daddr, xfrm_address_t *saddr) +__xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl) { /* Initialize temporary selector matching only * to current session. */ - ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst); - ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src); - x->sel.dport = xfrm_flowi_dport(fl); - x->sel.dport_mask = htons(0xffff); - x->sel.sport = xfrm_flowi_sport(fl); - x->sel.sport_mask = htons(0xffff); - x->sel.family = AF_INET6; - x->sel.prefixlen_d = 128; - x->sel.prefixlen_s = 128; - x->sel.proto = fl->proto; - x->sel.ifindex = fl->oif; + ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl->fl6_dst); + ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl->fl6_src); + sel->dport = xfrm_flowi_dport(fl); + sel->dport_mask = htons(0xffff); + sel->sport = xfrm_flowi_sport(fl); + sel->sport_mask = htons(0xffff); + sel->family = AF_INET6; + sel->prefixlen_d = 128; + sel->prefixlen_s = 128; + sel->proto = fl->proto; + sel->ifindex = fl->oif; +} + +static void +xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl, + xfrm_address_t *daddr, xfrm_address_t *saddr) +{ x->id = tmpl->id; if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); @@ -168,6 +172,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { .eth_proto = htons(ETH_P_IPV6), .owner = THIS_MODULE, .init_tempsel = __xfrm6_init_tempsel, + .init_temprop = xfrm6_init_temprop, .tmpl_sort = __xfrm6_tmpl_sort, .state_sort = __xfrm6_state_sort, .output = xfrm6_output, diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 023ba82..5826129 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -1024,7 +1024,8 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, { struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - int rc = -EINVAL, opt; + unsigned int opt; + int rc = -EINVAL; lock_sock(sk); if (unlikely(level != SOL_LLC || optlen != sizeof(int))) diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index e4dae02..cf4aea3 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -689,7 +689,7 @@ static void llc_station_rcv(struct sk_buff *skb) int __init llc_station_init(void) { - u16 rc = -ENOBUFS; + int rc = -ENOBUFS; struct sk_buff *skb; struct llc_station_state_ev *ev; diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c893f23..8f23401 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -175,6 +175,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); + del_timer_sync(&tid_tx->addba_resp_timer); + /* * After this packets are no longer handed right through * to the driver but are put onto tid_tx->pending instead, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fa0f37e..28624282 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2199,9 +2199,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, struct net_device *prev_dev = NULL; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - if (status->flag & RX_FLAG_INTERNAL_CMTR) - goto out_free_skb; - if (skb_headroom(skb) < sizeof(*rthdr) && pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) goto out_free_skb; @@ -2260,7 +2257,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, } else goto out_free_skb; - status->flag |= RX_FLAG_INTERNAL_CMTR; return; out_free_skb: diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 10caec5..34da679 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -377,7 +377,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) { skb2->dev = prev_dev; - netif_receive_skb(skb2); + netif_rx(skb2); } } @@ -386,7 +386,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) } if (prev_dev) { skb->dev = prev_dev; - netif_receive_skb(skb); + netif_rx(skb); skb = NULL; } rcu_read_unlock(); diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 7dcf7a4..8d9e4c9 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -48,15 +48,17 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) { unsigned int off, len; struct nf_ct_ext_type *t; + size_t alloc_size; rcu_read_lock(); t = rcu_dereference(nf_ct_ext_types[id]); BUG_ON(t == NULL); off = ALIGN(sizeof(struct nf_ct_ext), t->align); len = off + t->len; + alloc_size = t->alloc_size; rcu_read_unlock(); - *ext = kzalloc(t->alloc_size, gfp); + *ext = kzalloc(alloc_size, gfp); if (!*ext) return NULL; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 53d8922..f64de95 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1376,7 +1376,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, unsigned int msglen, origlen; const char *dptr, *end; s16 diff, tdiff = 0; - int ret; + int ret = NF_ACCEPT; typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust; if (ctinfo != IP_CT_ESTABLISHED && diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c index 5490fc3..daab8c4 100644 --- a/net/netfilter/nf_tproxy_core.c +++ b/net/netfilter/nf_tproxy_core.c @@ -70,7 +70,11 @@ nf_tproxy_destructor(struct sk_buff *skb) int nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk) { - if (inet_sk(sk)->transparent) { + bool transparent = (sk->sk_state == TCP_TIME_WAIT) ? + inet_twsk(sk)->tw_transparent : + inet_sk(sk)->transparent; + + if (transparent) { skb_orphan(skb); skb->sk = sk; skb->destructor = nf_tproxy_destructor; diff --git a/net/phonet/pep.c b/net/phonet/pep.c index b2a3ae6..1500302 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -225,12 +225,13 @@ static void pipe_grant_credits(struct sock *sk) static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb) { struct pep_sock *pn = pep_sk(sk); - struct pnpipehdr *hdr = pnp_hdr(skb); + struct pnpipehdr *hdr; int wake = 0; if (!pskb_may_pull(skb, sizeof(*hdr) + 4)) return -EINVAL; + hdr = pnp_hdr(skb); if (hdr->data[0] != PN_PEP_TYPE_COMMON) { LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n", (unsigned)hdr->data[0]); diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index c397524..c519939 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c @@ -43,7 +43,7 @@ void rds_tcp_state_change(struct sock *sk) struct rds_connection *conn; struct rds_tcp_connection *tc; - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); conn = sk->sk_user_data; if (conn == NULL) { state_change = sk->sk_state_change; @@ -68,7 +68,7 @@ void rds_tcp_state_change(struct sock *sk) break; } out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); state_change(sk); } diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 975183f..27844f2 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -114,7 +114,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes) rdsdebug("listen data ready sk %p\n", sk); - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); ready = sk->sk_user_data; if (ready == NULL) { /* check for teardown race */ ready = sk->sk_data_ready; @@ -131,7 +131,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes) queue_work(rds_wq, &rds_tcp_listen_work); out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); ready(sk, bytes); } diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index 1aba687..e437974 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c @@ -324,7 +324,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes) rdsdebug("data ready sk %p bytes %d\n", sk, bytes); - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); conn = sk->sk_user_data; if (conn == NULL) { /* check for teardown race */ ready = sk->sk_data_ready; @@ -338,7 +338,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes) if (rds_tcp_read_sock(conn, GFP_ATOMIC, KM_SOFTIRQ0) == -ENOMEM) queue_delayed_work(rds_wq, &conn->c_recv_w, 0); out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); ready(sk, bytes); } diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c index a28b895..2f012a0 100644 --- a/net/rds/tcp_send.c +++ b/net/rds/tcp_send.c @@ -224,7 +224,7 @@ void rds_tcp_write_space(struct sock *sk) struct rds_connection *conn; struct rds_tcp_connection *tc; - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); conn = sk->sk_user_data; if (conn == NULL) { write_space = sk->sk_write_space; @@ -244,7 +244,7 @@ void rds_tcp_write_space(struct sock *sk) queue_delayed_work(rds_wq, &conn->c_send_w, 0); out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); /* * write_space is only called when data leaves tcp's send queue if diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 8e45e76..d952e7e 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -679,7 +679,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1) return -EINVAL; - if (addr->srose_ndigis > ROSE_MAX_DIGIS) + if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) return -EINVAL; if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { @@ -739,7 +739,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1) return -EINVAL; - if (addr->srose_ndigis > ROSE_MAX_DIGIS) + if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) return -EINVAL; /* Source + Destination digis should not exceed ROSE_MAX_DIGIS */ diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 7416a5c..b0c2a82 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -137,7 +137,7 @@ next_knode: int toff = off + key->off + (off2 & key->offmask); __be32 *data, _data; - if (skb_headroom(skb) + toff < 0) + if (skb_headroom(skb) + toff > INT_MAX) goto out; data = skb_header_pointer(skb, toff, 4, &_data); diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 34066278..6318e11 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -255,10 +255,6 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, error = -EINVAL; goto err_out; } - if (!list_empty(&flow->list)) { - error = -EEXIST; - goto err_out; - } } else { int i; unsigned long cl; diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 8636639..ddbbf7c 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -543,16 +543,20 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) id = ntohs(hmacs->hmac_ids[i]); /* Check the id is in the supported range */ - if (id > SCTP_AUTH_HMAC_ID_MAX) + if (id > SCTP_AUTH_HMAC_ID_MAX) { + id = 0; continue; + } /* See is we support the id. Supported IDs have name and * length fields set, so that we can allocated and use * them. We can safely just check for name, for without the * name, we can't allocate the TFM. */ - if (!sctp_hmac_list[id].hmac_name) + if (!sctp_hmac_list[id].hmac_name) { + id = 0; continue; + } break; } diff --git a/net/sctp/output.c b/net/sctp/output.c index a646681..bcc4590 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -92,7 +92,6 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet, SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); - sctp_packet_reset(packet); packet->vtag = vtag; if (ecn_capable && sctp_packet_empty(packet)) { diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ca44917..fbb7077 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -916,6 +916,11 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, /* Walk through the addrs buffer and count the number of addresses. */ addr_buf = kaddrs; while (walk_size < addrs_size) { + if (walk_size + sizeof(sa_family_t) > addrs_size) { + kfree(kaddrs); + return -EINVAL; + } + sa_addr = (struct sockaddr *)addr_buf; af = sctp_get_af_specific(sa_addr->sa_family); @@ -1002,9 +1007,13 @@ static int __sctp_connect(struct sock* sk, /* Walk through the addrs buffer and count the number of addresses. */ addr_buf = kaddrs; while (walk_size < addrs_size) { + if (walk_size + sizeof(sa_family_t) > addrs_size) { + err = -EINVAL; + goto out_free; + } + sa_addr = (union sctp_addr *)addr_buf; af = sctp_get_af_specific(sa_addr->sa.sa_family); - port = ntohs(sa_addr->v4.sin_port); /* If the address family is not supported or if this address * causes the address buffer to overflow return EINVAL. @@ -1014,6 +1023,8 @@ static int __sctp_connect(struct sock* sk, goto out_free; } + port = ntohs(sa_addr->v4.sin_port); + /* Save current address so we can work with it */ memcpy(&to, sa_addr, af->sockaddr_len); diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 36cb660..e9eaaf7 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -38,7 +38,7 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { static LIST_HEAD(cred_unused); static unsigned long number_cred_unused; -#define MAX_HASHTABLE_BITS (10) +#define MAX_HASHTABLE_BITS (14) static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) { unsigned long num; diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index dcfc66b..12c4859 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode) struct rpc_inode *rpci = RPC_I(inode); struct gss_upcall_msg *gss_msg; +restart: spin_lock(&inode->i_lock); - while (!list_empty(&rpci->in_downcall)) { + list_for_each_entry(gss_msg, &rpci->in_downcall, list) { - gss_msg = list_entry(rpci->in_downcall.next, - struct gss_upcall_msg, list); + if (!list_empty(&gss_msg->msg.list)) + continue; gss_msg->msg.errno = -EPIPE; atomic_inc(&gss_msg->count); __gss_unhash_msg(gss_msg); spin_unlock(&inode->i_lock); gss_release_msg(gss_msg); - spin_lock(&inode->i_lock); + goto restart; } spin_unlock(&inode->i_lock); diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 0326446..778e5df 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -237,6 +237,7 @@ get_key(const void *p, const void *end, if (!supported_gss_krb5_enctype(alg)) { printk(KERN_WARNING "gss_kerberos_mech: unsupported " "encryption key algorithm %d\n", alg); + p = ERR_PTR(-EINVAL); goto out_err; } p = simple_get_netobj(p, end, &key); @@ -282,15 +283,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) ctx->enctype = ENCTYPE_DES_CBC_RAW; ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); - if (ctx->gk5e == NULL) + if (ctx->gk5e == NULL) { + p = ERR_PTR(-EINVAL); goto out_err; + } /* The downcall format was designed before we completely understood * the uses of the context fields; so it includes some stuff we * just give some minimal sanity-checking, and some we ignore * completely (like the next twenty bytes): */ - if (unlikely(p + 20 > end || p + 20 < p)) + if (unlikely(p + 20 > end || p + 20 < p)) { + p = ERR_PTR(-EFAULT); goto out_err; + } p += 20; p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); if (IS_ERR(p)) @@ -619,6 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, if (ctx->seq_send64 != ctx->seq_send) { dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, (long unsigned)ctx->seq_send64, ctx->seq_send); + p = ERR_PTR(-EINVAL); goto out_err; } p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index dc3f1f5..adade3d 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c @@ -100,6 +100,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, if (version != 1) { dprintk("RPC: unknown spkm3 token format: " "obsolete nfs-utils?\n"); + p = ERR_PTR(-EINVAL); goto out_err_free_ctx; } @@ -135,8 +136,10 @@ gss_import_sec_context_spkm3(const void *p, size_t len, if (IS_ERR(p)) goto out_err_free_intg_alg; - if (p != end) + if (p != end) { + p = ERR_PTR(-EFAULT); goto out_err_free_intg_key; + } ctx_id->internal_ctx_id = ctx; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2388d83..fa55490 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru goto out_no_principal; } - kref_init(&clnt->cl_kref); + atomic_set(&clnt->cl_count, 1); err = rpc_setup_pipedir(clnt, program->pipe_dir_name); if (err < 0) @@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt) if (new->cl_principal == NULL) goto out_no_principal; } - kref_init(&new->cl_kref); + atomic_set(&new->cl_count, 1); err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); if (err != 0) goto out_no_path; if (new->cl_auth) atomic_inc(&new->cl_auth->au_count); xprt_get(clnt->cl_xprt); - kref_get(&clnt->cl_kref); + atomic_inc(&clnt->cl_count); rpc_register_client(new); rpciod_up(); return new; @@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); * Free an RPC client */ static void -rpc_free_client(struct kref *kref) +rpc_free_client(struct rpc_clnt *clnt) { - struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); - dprintk("RPC: destroying %s client for %s\n", clnt->cl_protname, clnt->cl_server); if (!IS_ERR(clnt->cl_path.dentry)) { @@ -495,12 +493,10 @@ out_free: * Free an RPC client */ static void -rpc_free_auth(struct kref *kref) +rpc_free_auth(struct rpc_clnt *clnt) { - struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); - if (clnt->cl_auth == NULL) { - rpc_free_client(kref); + rpc_free_client(clnt); return; } @@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref) * release remaining GSS contexts. This mechanism ensures * that it can do so safely. */ - kref_init(kref); + atomic_inc(&clnt->cl_count); rpcauth_release(clnt->cl_auth); clnt->cl_auth = NULL; - kref_put(kref, rpc_free_client); + if (atomic_dec_and_test(&clnt->cl_count)) + rpc_free_client(clnt); } /* @@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt) if (list_empty(&clnt->cl_tasks)) wake_up(&destroy_wait); - kref_put(&clnt->cl_kref, rpc_free_auth); + if (atomic_dec_and_test(&clnt->cl_count)) + rpc_free_auth(clnt); } /** @@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) if (clnt != NULL) { rpc_task_release_client(task); task->tk_client = clnt; - kref_get(&clnt->cl_kref); + atomic_inc(&clnt->cl_count); if (clnt->cl_softrtry) task->tk_flags |= RPC_TASK_SOFT; /* Add to the client's list of all tasks */ @@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task) task->tk_status = 0; if (status >= 0) { if (task->tk_rqstp) { - task->tk_action = call_allocate; + task->tk_action = call_refresh; return; } @@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task) } /* - * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. + * 2. Bind and/or refresh the credentials + */ +static void +call_refresh(struct rpc_task *task) +{ + dprint_status(task); + + task->tk_action = call_refreshresult; + task->tk_status = 0; + task->tk_client->cl_stats->rpcauthrefresh++; + rpcauth_refreshcred(task); +} + +/* + * 2a. Process the results of a credential refresh + */ +static void +call_refreshresult(struct rpc_task *task) +{ + int status = task->tk_status; + + dprint_status(task); + + task->tk_status = 0; + task->tk_action = call_allocate; + if (status >= 0 && rpcauth_uptodatecred(task)) + return; + switch (status) { + case -EACCES: + rpc_exit(task, -EACCES); + return; + case -ENOMEM: + rpc_exit(task, -ENOMEM); + return; + case -ETIMEDOUT: + rpc_delay(task, 3*HZ); + } + task->tk_action = call_refresh; +} + +/* + * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. * (Note: buffer memory is freed in xprt_release). */ static void call_allocate(struct rpc_task *task) { - unsigned int slack = task->tk_client->cl_auth->au_cslack; + unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = task->tk_xprt; struct rpc_procinfo *proc = task->tk_msg.rpc_proc; @@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task) dprint_status(task); task->tk_status = 0; - task->tk_action = call_refresh; + task->tk_action = call_bind; if (req->rq_buffer) return; @@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task) rpc_exit(task, -ERESTARTSYS); } -/* - * 2a. Bind and/or refresh the credentials - */ -static void -call_refresh(struct rpc_task *task) -{ - dprint_status(task); - - task->tk_action = call_refreshresult; - task->tk_status = 0; - task->tk_client->cl_stats->rpcauthrefresh++; - rpcauth_refreshcred(task); -} - -/* - * 2b. Process the results of a credential refresh - */ -static void -call_refreshresult(struct rpc_task *task) -{ - int status = task->tk_status; - - dprint_status(task); - - task->tk_status = 0; - task->tk_action = call_bind; - if (status >= 0 && rpcauth_uptodatecred(task)) - return; - switch (status) { - case -EACCES: - rpc_exit(task, -EACCES); - return; - case -ENOMEM: - rpc_exit(task, -ENOMEM); - return; - case -ETIMEDOUT: - rpc_delay(task, 3*HZ); - } - task->tk_action = call_refresh; -} - static inline int rpc_task_need_encode(struct rpc_task *task) { diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 95ccbcf..8c8eef2 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -48,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, return; do { msg = list_entry(head->next, struct rpc_pipe_msg, list); - list_del(&msg->list); + list_del_init(&msg->list); msg->errno = err; destroy_msg(msg); } while (!list_empty(head)); @@ -208,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) if (msg != NULL) { spin_lock(&inode->i_lock); msg->errno = -EAGAIN; - list_del(&msg->list); + list_del_init(&msg->list); spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } @@ -268,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) if (res < 0 || msg->len == msg->copied) { filp->private_data = NULL; spin_lock(&inode->i_lock); - list_del(&msg->list); + list_del_init(&msg->list); spin_unlock(&inode->i_lock); rpci->ops->destroy_msg(msg); } @@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) static int rpc_info_open(struct inode *inode, struct file *file) { - struct rpc_clnt *clnt; + struct rpc_clnt *clnt = NULL; int ret = single_open(file, rpc_show_info, NULL); if (!ret) { struct seq_file *m = file->private_data; - mutex_lock(&inode->i_mutex); - clnt = RPC_I(inode)->private; - if (clnt) { - kref_get(&clnt->cl_kref); + + spin_lock(&file->f_path.dentry->d_lock); + if (!d_unhashed(file->f_path.dentry)) + clnt = RPC_I(inode)->private; + if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { + spin_unlock(&file->f_path.dentry->d_lock); m->private = clnt; } else { + spin_unlock(&file->f_path.dentry->d_lock); single_release(inode, file); ret = -EINVAL; } - mutex_unlock(&inode->i_mutex); } return ret; } diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index b6309db..fe9306b 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -800,7 +800,7 @@ static void xs_udp_data_ready(struct sock *sk, int len) u32 _xid; __be32 *xp; - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); dprintk("RPC: xs_udp_data_ready...\n"); if (!(xprt = xprt_from_sock(sk))) goto out; @@ -852,7 +852,7 @@ static void xs_udp_data_ready(struct sock *sk, int len) dropit: skb_free_datagram(sk, skb); out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); } static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) @@ -1229,7 +1229,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes) dprintk("RPC: xs_tcp_data_ready...\n"); - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); if (!(xprt = xprt_from_sock(sk))) goto out; if (xprt->shutdown) @@ -1248,7 +1248,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes) read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv); } while (read > 0); out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); } /* @@ -1301,7 +1301,7 @@ static void xs_tcp_state_change(struct sock *sk) { struct rpc_xprt *xprt; - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); if (!(xprt = xprt_from_sock(sk))) goto out; dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); @@ -1313,7 +1313,7 @@ static void xs_tcp_state_change(struct sock *sk) switch (sk->sk_state) { case TCP_ESTABLISHED: - spin_lock_bh(&xprt->transport_lock); + spin_lock(&xprt->transport_lock); if (!xprt_test_and_set_connected(xprt)) { struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); @@ -1327,7 +1327,7 @@ static void xs_tcp_state_change(struct sock *sk) xprt_wake_pending_tasks(xprt, -EAGAIN); } - spin_unlock_bh(&xprt->transport_lock); + spin_unlock(&xprt->transport_lock); break; case TCP_FIN_WAIT1: /* The client initiated a shutdown of the socket */ @@ -1365,7 +1365,7 @@ static void xs_tcp_state_change(struct sock *sk) xs_sock_mark_closed(xprt); } out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); } /** @@ -1376,7 +1376,7 @@ static void xs_error_report(struct sock *sk) { struct rpc_xprt *xprt; - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); if (!(xprt = xprt_from_sock(sk))) goto out; dprintk("RPC: %s client %p...\n" @@ -1384,7 +1384,7 @@ static void xs_error_report(struct sock *sk) __func__, xprt, sk->sk_err); xprt_wake_pending_tasks(xprt, -EAGAIN); out: - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); } static void xs_write_space(struct sock *sk) @@ -1416,13 +1416,13 @@ static void xs_write_space(struct sock *sk) */ static void xs_udp_write_space(struct sock *sk) { - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); /* from net/core/sock.c:sock_def_write_space */ if (sock_writeable(sk)) xs_write_space(sk); - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); } /** @@ -1437,13 +1437,13 @@ static void xs_udp_write_space(struct sock *sk) */ static void xs_tcp_write_space(struct sock *sk) { - read_lock(&sk->sk_callback_lock); + read_lock_bh(&sk->sk_callback_lock); /* from net/core/stream.c:sk_stream_write_space */ if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) xs_write_space(sk); - read_unlock(&sk->sk_callback_lock); + read_unlock_bh(&sk->sk_callback_lock); } static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt) diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c index 3feb28e..674d426 100644 --- a/net/wireless/wext-priv.c +++ b/net/wireless/wext-priv.c @@ -152,7 +152,7 @@ static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, } else if (!iwp->pointer) return -EFAULT; - extra = kmalloc(extra_size, GFP_KERNEL); + extra = kzalloc(extra_size, GFP_KERNEL); if (!extra) return -ENOMEM; diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index a3cca0a..64f2ae1 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -101,7 +101,7 @@ resume: err = -EHOSTUNREACH; goto error_nolock; } - skb_dst_set_noref(skb, dst); + skb_dst_set(skb, dst_clone(dst)); x = dst->xfrm; } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2b3ed7a..cbab6e1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1175,9 +1175,8 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, tmpl->mode == XFRM_MODE_BEET) { remote = &tmpl->id.daddr; local = &tmpl->saddr; - family = tmpl->encap_family; - if (xfrm_addr_any(local, family)) { - error = xfrm_get_saddr(net, &tmp, remote, family); + if (xfrm_addr_any(local, tmpl->encap_family)) { + error = xfrm_get_saddr(net, &tmp, remote, tmpl->encap_family); if (error) goto fail; local = &tmp; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5208b12f..eb96ce5 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -656,15 +656,23 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si) EXPORT_SYMBOL(xfrm_sad_getinfo); static int -xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, - struct xfrm_tmpl *tmpl, - xfrm_address_t *daddr, xfrm_address_t *saddr, - unsigned short family) +xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl, + struct xfrm_tmpl *tmpl, + xfrm_address_t *daddr, xfrm_address_t *saddr, + unsigned short family) { struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); if (!afinfo) return -1; - afinfo->init_tempsel(x, fl, tmpl, daddr, saddr); + afinfo->init_tempsel(&x->sel, fl); + + if (family != tmpl->encap_family) { + xfrm_state_put_afinfo(afinfo); + afinfo = xfrm_state_get_afinfo(tmpl->encap_family); + if (!afinfo) + return -1; + } + afinfo->init_temprop(x, tmpl, daddr, saddr); xfrm_state_put_afinfo(afinfo); return 0; } @@ -790,37 +798,38 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, int error = 0; struct xfrm_state *best = NULL; u32 mark = pol->mark.v & pol->mark.m; + unsigned short encap_family = tmpl->encap_family; to_put = NULL; spin_lock_bh(&xfrm_state_lock); - h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); + h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family); hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { - if (x->props.family == family && + if (x->props.family == encap_family && x->props.reqid == tmpl->reqid && (mark & x->mark.m) == x->mark.v && !(x->props.flags & XFRM_STATE_WILDRECV) && - xfrm_state_addr_check(x, daddr, saddr, family) && + xfrm_state_addr_check(x, daddr, saddr, encap_family) && tmpl->mode == x->props.mode && tmpl->id.proto == x->id.proto && (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) - xfrm_state_look_at(pol, x, fl, family, daddr, saddr, + xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr, &best, &acquire_in_progress, &error); } if (best) goto found; - h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); + h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family); hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { - if (x->props.family == family && + if (x->props.family == encap_family && x->props.reqid == tmpl->reqid && (mark & x->mark.m) == x->mark.v && !(x->props.flags & XFRM_STATE_WILDRECV) && - xfrm_state_addr_check(x, daddr, saddr, family) && + xfrm_state_addr_check(x, daddr, saddr, encap_family) && tmpl->mode == x->props.mode && tmpl->id.proto == x->id.proto && (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) - xfrm_state_look_at(pol, x, fl, family, daddr, saddr, + xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr, &best, &acquire_in_progress, &error); } @@ -829,7 +838,7 @@ found: if (!x && !error && !acquire_in_progress) { if (tmpl->id.spi && (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi, - tmpl->id.proto, family)) != NULL) { + tmpl->id.proto, encap_family)) != NULL) { to_put = x0; error = -EEXIST; goto out; @@ -839,9 +848,9 @@ found: error = -ENOMEM; goto out; } - /* Initialize temporary selector matching only + /* Initialize temporary state matching only * to current session. */ - xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); + xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family); memcpy(&x->mark, &pol->mark, sizeof(x->mark)); error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); @@ -856,10 +865,10 @@ found: x->km.state = XFRM_STATE_ACQ; list_add(&x->km.all, &net->xfrm.state_all); hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); - h = xfrm_src_hash(net, daddr, saddr, family); + h = xfrm_src_hash(net, daddr, saddr, encap_family); hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); if (x->id.spi) { - h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); + h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family); hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); } x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; diff --git a/samples/kfifo/dma-example.c b/samples/kfifo/dma-example.c index ee03a4f..0647379 100644 --- a/samples/kfifo/dma-example.c +++ b/samples/kfifo/dma-example.c @@ -24,6 +24,7 @@ static int __init example_init(void) { int i; unsigned int ret; + unsigned int nents; struct scatterlist sg[10]; printk(KERN_INFO "DMA fifo test start\n"); @@ -61,9 +62,9 @@ static int __init example_init(void) * byte at the beginning, after the kfifo_skip(). */ sg_init_table(sg, ARRAY_SIZE(sg)); - ret = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE); - printk(KERN_INFO "DMA sgl entries: %d\n", ret); - if (!ret) { + nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE); + printk(KERN_INFO "DMA sgl entries: %d\n", nents); + if (!nents) { /* fifo is full and no sgl was created */ printk(KERN_WARNING "error kfifo_dma_in_prepare\n"); return -EIO; @@ -71,7 +72,7 @@ static int __init example_init(void) /* receive data */ printk(KERN_INFO "scatterlist for receive:\n"); - for (i = 0; i < ARRAY_SIZE(sg); i++) { + for (i = 0; i < nents; i++) { printk(KERN_INFO "sg[%d] -> " "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", @@ -91,16 +92,16 @@ static int __init example_init(void) kfifo_dma_in_finish(&fifo, ret); /* Prepare to transmit data, example: 8 bytes */ - ret = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8); - printk(KERN_INFO "DMA sgl entries: %d\n", ret); - if (!ret) { + nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8); + printk(KERN_INFO "DMA sgl entries: %d\n", nents); + if (!nents) { /* no data was available and no sgl was created */ printk(KERN_WARNING "error kfifo_dma_out_prepare\n"); return -EIO; } printk(KERN_INFO "scatterlist for transmit:\n"); - for (i = 0; i < ARRAY_SIZE(sg); i++) { + for (i = 0; i < nents; i++) { printk(KERN_INFO "sg[%d] -> " "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 5b7c86e..7ef429c 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -427,7 +427,7 @@ static void check_conf(struct menu *menu) if (sym->name && !sym_is_choice_value(sym)) { printf("CONFIG_%s\n", sym->name); } - } else { + } else if (input_mode != oldnoconfig) { if (!conf_cnt++) printf(_("*\n* Restart config...\n*\n")); rootEntry = menu_get_parent_menu(menu); diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 6ee2e4f..170459c 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -165,7 +165,6 @@ struct menu { struct symbol *sym; struct property *prompt; struct expr *dep; - struct expr *dir_dep; unsigned int flags; char *help; struct file *file; diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 4fb5902..edda8b4 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -107,7 +107,6 @@ static struct expr *menu_check_dep(struct expr *e) void menu_add_dep(struct expr *dep) { current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); - current_entry->dir_dep = current_entry->dep; } void menu_set_type(int type) @@ -291,10 +290,6 @@ void menu_finalize(struct menu *parent) for (menu = parent->list; menu; menu = menu->next) menu_finalize(menu); } else if (sym) { - /* ignore inherited dependencies for dir_dep */ - sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep)); - sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr); - basedep = parent->prompt ? parent->prompt->visible.expr : NULL; basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); basedep = expr_eliminate_dups(expr_transform(basedep)); @@ -325,6 +320,8 @@ void menu_finalize(struct menu *parent) parent->next = last_menu->next; last_menu->next = NULL; } + + sym->dir_dep.expr = parent->dep; } for (menu = parent->list; menu; menu = menu->next) { if (sym && sym_is_choice(sym) && diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 943712c..1f8b305 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -350,6 +350,7 @@ void sym_calc_value(struct symbol *sym) } } calc_newval: +#if 0 if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { fprintf(stderr, "warning: ("); expr_fprint(sym->rev_dep.expr, stderr); @@ -358,6 +359,7 @@ void sym_calc_value(struct symbol *sym) expr_fprint(sym->dir_dep.expr, stderr); fprintf(stderr, ")\n"); } +#endif newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); } if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ef43995..c668b44 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1416,15 +1416,19 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) const pid_t gpid = task_pid_nr(current); static const int tomoyo_buffer_len = 4096; char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); + pid_t ppid; if (!buffer) return NULL; do_gettimeofday(&tv); + rcu_read_lock(); + ppid = task_tgid_vnr(current->real_parent); + rcu_read_unlock(); snprintf(buffer, tomoyo_buffer_len - 1, "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid, - (pid_t) sys_getpid(), (pid_t) sys_getppid(), + task_tgid_vnr(current), ppid, current_uid(), current_gid(), current_euid(), current_egid(), current_suid(), current_sgid(), current_fsuid(), current_fsgid()); diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 04454cb..7c66bd8 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -689,9 +689,6 @@ struct tomoyo_profile { /********** Function prototypes. **********/ -extern asmlinkage long sys_getpid(void); -extern asmlinkage long sys_getppid(void); - /* Check whether the given string starts with the given keyword. */ bool tomoyo_str_starts(char **src, const char *find); /* Get tomoyo_realpath() of current process. */ diff --git a/sound/core/control.c b/sound/core/control.c index 070aab4..45a8180 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -31,6 +31,7 @@ /* max number of user-defined controls */ #define MAX_USER_CONTROLS 32 +#define MAX_CONTROL_COUNT 1028 struct snd_kctl_ioctl { struct list_head list; /* list of all ioctls */ @@ -195,6 +196,10 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, if (snd_BUG_ON(!control || !control->count)) return NULL; + + if (control->count > MAX_CONTROL_COUNT) + return NULL; + kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL); if (kctl == NULL) { snd_printk(KERN_ERR "Cannot allocate control instance\n"); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 204af48..ac242a3 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -372,14 +372,17 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_runtime *runtime; + + mutex_lock(&substream->pcm->open_mutex); + runtime = substream->runtime; if (!runtime) { snd_iprintf(buffer, "closed\n"); - return; + goto unlock; } if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); - return; + goto unlock; } snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format)); @@ -398,20 +401,25 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); } #endif + unlock: + mutex_unlock(&substream->pcm->open_mutex); } static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_runtime *runtime; + + mutex_lock(&substream->pcm->open_mutex); + runtime = substream->runtime; if (!runtime) { snd_iprintf(buffer, "closed\n"); - return; + goto unlock; } if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); - return; + goto unlock; } snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); snd_iprintf(buffer, "period_step: %u\n", runtime->period_step); @@ -421,24 +429,29 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); + unlock: + mutex_unlock(&substream->pcm->open_mutex); } static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_runtime *runtime; struct snd_pcm_status status; int err; + + mutex_lock(&substream->pcm->open_mutex); + runtime = substream->runtime; if (!runtime) { snd_iprintf(buffer, "closed\n"); - return; + goto unlock; } memset(&status, 0, sizeof(status)); err = snd_pcm_status(substream, &status); if (err < 0) { snd_iprintf(buffer, "error %d\n", err); - return; + goto unlock; } snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state)); snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid)); @@ -452,6 +465,8 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, snd_iprintf(buffer, "-----\n"); snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr); snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr); + unlock: + mutex_unlock(&substream->pcm->open_mutex); } #ifdef CONFIG_SND_PCM_XRUN_DEBUG diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 134fc6c..d4eb2ef 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1992,6 +1992,8 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) substream->ops->close(substream); substream->hw_opened = 0; } + if (pm_qos_request_active(&substream->latency_pm_qos_req)) + pm_qos_remove_request(&substream->latency_pm_qos_req); if (substream->pcm_release) { substream->pcm_release(substream); substream->pcm_release = NULL; diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 1adb8a3..42d7844 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c @@ -900,7 +900,7 @@ static int proc_init(struct snd_akm4xxx *ak) return 0; } #else /* !CONFIG_PROC_FS */ -static int proc_init(struct snd_akm4xxx *ak) {} +static int proc_init(struct snd_akm4xxx *ak) { return 0; } #endif int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 92aa762..07f803e 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -391,11 +391,11 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: - return audio_ioctl(dev, file, cmd, p); + ret = audio_ioctl(dev, file, cmd, p); break; case SND_DEV_MIDIN: - return MIDIbuf_ioctl(dev, file, cmd, p); + ret = MIDIbuf_ioctl(dev, file, cmd, p); break; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1053fff..34940a0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -126,6 +126,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ICH10}," "{Intel, PCH}," "{Intel, CPT}," + "{Intel, PBG}," "{Intel, SCH}," "{ATI, SB450}," "{ATI, SB600}," @@ -2749,6 +2750,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH }, /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, + /* PBG */ + { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, /* ATI SB 450/600 */ diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index b697fd2..10bbbaf 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3641,6 +3641,7 @@ static struct snd_pci_quirk ad1984_cfg_tbl[] = { /* Lenovo Thinkpad T61/X61 */ SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), + SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP), {} }; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 71f9d64..972e7c4 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3092,6 +3092,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), + SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 69b950d..baa108b 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c @@ -84,7 +84,7 @@ static struct hda_verb nvhdmi_basic_init_7x[] = { #else /* support all rates and formats */ #define SUPPORTED_RATES \ - (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ SNDRV_PCM_RATE_192000) #define SUPPORTED_MAXBPS 24 diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bcbf916..a432e6e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1594,12 +1594,22 @@ static void alc_auto_parse_digital(struct hda_codec *codec) } if (spec->autocfg.dig_in_pin) { - hda_nid_t dig_nid; - err = snd_hda_get_connections(codec, - spec->autocfg.dig_in_pin, - &dig_nid, 1); - if (err > 0) - spec->dig_in_nid = dig_nid; + dig_nid = codec->start_nid; + for (i = 0; i < codec->num_nodes; i++, dig_nid++) { + unsigned int wcaps = get_wcaps(codec, dig_nid); + if (get_wcaps_type(wcaps) != AC_WID_AUD_IN) + continue; + if (!(wcaps & AC_WCAP_DIGITAL)) + continue; + if (!(wcaps & AC_WCAP_CONN_LIST)) + continue; + err = get_connection_index(codec, dig_nid, + spec->autocfg.dig_in_pin); + if (err >= 0) { + spec->dig_in_nid = dig_nid; + break; + } + } } } @@ -14453,6 +14463,7 @@ static void alc269_auto_init(struct hda_codec *codec) enum { ALC269_FIXUP_SONY_VAIO, + ALC269_FIXUP_DELL_M101Z, }; static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { @@ -14464,11 +14475,20 @@ static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_SONY_VAIO] = { .verbs = alc269_sony_vaio_fixup_verbs }, + [ALC269_FIXUP_DELL_M101Z] = { + .verbs = (const struct hda_verb[]) { + /* Enables internal speaker */ + {0x20, AC_VERB_SET_COEF_INDEX, 13}, + {0x20, AC_VERB_SET_PROC_COEF, 0x4040}, + {} + } + }, }; static struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), {} }; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 95148e5..c16c5ba 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1747,6 +1747,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "HP dv6", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061, "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */ + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e, + "HP DV6", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, "HP", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 289cb4d..6c0a11a 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c @@ -543,6 +543,10 @@ static int __devinit get_oxygen_model(struct oxygen *chip, chip->model.suspend = claro_suspend; chip->model.resume = claro_resume; chip->model.set_adc_params = set_ak5385_params; + chip->model.device_config = PLAYBACK_0_TO_I2S | + PLAYBACK_1_TO_SPDIF | + CAPTURE_0_FROM_I2S_2 | + CAPTURE_1_FROM_SPDIF; break; } if (id->driver_data == MODEL_MERIDIAN || diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index b92adef..d6fa7bf 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -4609,6 +4609,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne if (err < 0) return err; + memset(&info, 0, sizeof(info)); spin_lock_irqsave(&hdsp->lock, flags); info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 547b713..0c98ef9 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -4127,6 +4127,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: + memset(&info, 0, sizeof(info)); spin_lock_irq(&hdspm->lock); info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 2f12da4..581a670 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -579,7 +579,7 @@ static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream, rate * delay_ms / 1000) * substream->runtime->channels; - pr_debug(KERN_ERR "%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n", + pr_debug("%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n", __func__, delay_ms, rate, diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c index 1b61c23..f1b1bc4 100644 --- a/sound/soc/s3c24xx/s3c-dma.c +++ b/sound/soc/s3c24xx/s3c-dma.c @@ -94,8 +94,7 @@ static void s3c_dma_enqueue(struct snd_pcm_substream *substream) if ((pos + len) > prtd->dma_end) { len = prtd->dma_end - pos; - pr_debug(KERN_DEBUG "%s: corrected dma len %ld\n", - __func__, len); + pr_debug("%s: corrected dma len %ld\n", __func__, len); } ret = s3c2410_dma_enqueue(prtd->params->channel, diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index b823a5c..87e2b7f 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -12,6 +12,7 @@ #include <linux/firmware.h> #include <linux/module.h> +#include <asm/clkdev.h> #include <asm/clock.h> #include <cpu/sh7722.h> @@ -40,12 +41,12 @@ static struct clk_ops siumckb_clk_ops = { }; static struct clk siumckb_clk = { - .name = "siumckb_clk", - .id = -1, .ops = &siumckb_clk_ops, .rate = 0, /* initialised at run-time */ }; +static struct clk_lookup *siumckb_lookup; + static int migor_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -180,6 +181,13 @@ static int __init migor_init(void) if (ret < 0) return ret; + siumckb_lookup = clkdev_alloc(&siumckb_clk, "siumckb_clk", NULL); + if (!siumckb_lookup) { + ret = -ENOMEM; + goto eclkdevalloc; + } + clkdev_add(siumckb_lookup); + /* Port number used on this machine: port B */ migor_snd_device = platform_device_alloc("soc-audio", 1); if (!migor_snd_device) { @@ -200,12 +208,15 @@ static int __init migor_init(void) epdevadd: platform_device_put(migor_snd_device); epdevalloc: + clkdev_drop(siumckb_lookup); +eclkdevalloc: clk_unregister(&siumckb_clk); return ret; } static void __exit migor_exit(void) { + clkdev_drop(siumckb_lookup); clk_unregister(&siumckb_clk); platform_device_unregister(migor_snd_device); } diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index adbc68c..f6b0d28 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -203,8 +203,9 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, data[1] = (value >> 8) & 0xff; data[2] = value & 0xff; - if (!snd_soc_codec_volatile_register(codec, reg)) - reg_cache[reg] = value; + if (!snd_soc_codec_volatile_register(codec, reg) + && reg < codec->reg_cache_size) + reg_cache[reg] = value; if (codec->cache_only) { codec->cache_sync = 1; diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 4f1fa77..1950e19 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -1017,7 +1017,7 @@ builtin-revert.o wt-status.o: wt-status.h # we compile into subdirectories. if the target directory is not the source directory, they might not exists. So # we depend the various files onto their directories. DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h -$(DIRECTORY_DEPS): $(sort $(dir $(DIRECTORY_DEPS))) +$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS))) # In the second step, we make a rule to actually create these directories $(sort $(dir $(DIRECTORY_DEPS))): $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null diff --git a/tools/perf/perf.h b/tools/perf/perf.h index ef7aa0a..95aaf56 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -73,6 +73,18 @@ void get_term_dimensions(struct winsize *ws); #define cpu_relax() asm volatile("":::"memory") #endif +#ifdef __mips__ +#include "../../arch/mips/include/asm/unistd.h" +#define rmb() asm volatile( \ + ".set mips2\n\t" \ + "sync\n\t" \ + ".set mips0" \ + : /* no output */ \ + : /* no input */ \ + : "memory") +#define cpu_relax() asm volatile("" ::: "memory") +#endif + #include <time.h> #include <unistd.h> #include <sys/types.h> diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 7ea983a..f7af2fc 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -97,7 +97,7 @@ void setup_python_scripting(void) register_python_scripting(&python_scripting_unsupported_ops); } #else -struct scripting_ops python_scripting_ops; +extern struct scripting_ops python_scripting_ops; void setup_python_scripting(void) { @@ -158,7 +158,7 @@ void setup_perl_scripting(void) register_perl_scripting(&perl_scripting_unsupported_ops); } #else -struct scripting_ops perl_scripting_ops; +extern struct scripting_ops perl_scripting_ops; void setup_perl_scripting(void) { diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index dafdf67..6866aa4 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -773,7 +773,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name) switch (key) { case 'a': - if (browser->selection->map == NULL && + if (browser->selection->map == NULL || browser->selection->map->dso->annotate_warned) continue; goto do_annotate; diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index 66cf65b..c1f1e3c 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -218,7 +218,6 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) events = file->f_op->poll(file, &irqfd->pt); list_add_tail(&irqfd->list, &kvm->irqfds.items); - spin_unlock_irq(&kvm->irqfds.lock); /* * Check if there was an event already pending on the eventfd @@ -227,6 +226,8 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) if (events & POLLIN) schedule_work(&irqfd->inject); + spin_unlock_irq(&kvm->irqfds.lock); + /* * do not drop the file until the irqfd is fully initialized, otherwise * we might race against the POLLHUP diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index d4853a5..5186e72 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1970,10 +1970,12 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, asmlinkage void kvm_handle_fault_on_reboot(void) { - if (kvm_rebooting) + if (kvm_rebooting) { /* spin while reset goes on */ + local_irq_enable(); while (true) ; + } /* Fault while not rebooting. We want the trace. */ BUG(); } |