mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
ASoC: Fixes for v3.13
A smattering of fixes here, some core ones for the rate combination issues for things other than simple bitmasks, for readback of byte controls and for updating the power of value muxes plus a bunch of driver fixes of varying severity. The warning fix in the i.MX FIQ driver is fixing a warning introduced by a previous fix. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.15 (GNU/Linux) iQIcBAABAgAGBQJSnxQYAAoJELSic+t+oim9JPUQAJprZ2T8xrEV9IVDdu0P3HxB Mk6Hp2r+GjNDxjeKGtSer1uni35YHfQuMa79b+O3j7X35ufFPiJrwnSuzQJ6muHA nBmIeWC5aNC0JcOy+Ga/j22YnsuOtEJk/Hv1M6tLOMAHv+mWL0CgUVgc0YguOhJe bhpMx9Z1EfPkjfSp39uLIqrd9mpsLGm+VNmuNjZCs707EWVKEe2figcRDkabZQPg CdH7K65oEsxxzzvbs5HEByo/WKp43E4ENb7j8Y/2UutwxggWrCLf00d6qWMNBzCG 9Q+pXIY5M6FFpToyvi+w0W5vZdEony8qDN8P9VLIjzX4LkliIF+hYvtVtbHP87Ft +H7G7IHNeIQlac6w1d2hLfIBhocpGf8nX5kt7NyNU5J4Ceuv7FQTk5ZSGnjA9Oky 3scLM2Y5PNvSLFgXWmJHzcLd1PoGF+O9AHFOjZCES1si2yZRFdHth5Q5YHimozpQ dcVUGn/NfKmXD0PAXLj9Jfg2IhIqv1EFgSBtxCT2COfWhBS0bFLprxFT0p9SVzCC Cn5XPosBwmmbWqKWm+wORaWUz4f6gxFzKxGiGT8mUL8Xql3TGKXkXrVo7Io1hU+T P3ATiYoYaPasi5duJ0q9M6aiH1iY+D3PdD0b7VJMtb3uTl2bMcNDsZTmxt+Zo8lP pF67+iKpsaKYbqbvpCRm =Uu21 -----END PGP SIGNATURE----- Merge tag 'asoc-v3.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus ASoC: Fixes for v3.13 A smattering of fixes here, some core ones for the rate combination issues for things other than simple bitmasks, for readback of byte controls and for updating the power of value muxes plus a bunch of driver fixes of varying severity. The warning fix in the i.MX FIQ driver is fixing a warning introduced by a previous fix.
This commit is contained in:
commit
b0e6989c96
@ -196,13 +196,6 @@ chmod 0644 /dev/cpu/microcode
|
||||
as root before you can use this. You'll probably also want to
|
||||
get the user-space microcode_ctl utility to use with this.
|
||||
|
||||
Powertweak
|
||||
----------
|
||||
|
||||
If you are running v0.1.17 or earlier, you should upgrade to
|
||||
version v0.99.0 or higher. Running old versions may cause problems
|
||||
with programs using shared memory.
|
||||
|
||||
udev
|
||||
----
|
||||
udev is a userspace application for populating /dev dynamically with
|
||||
@ -366,10 +359,6 @@ Intel P6 microcode
|
||||
------------------
|
||||
o <http://www.urbanmyth.org/microcode/>
|
||||
|
||||
Powertweak
|
||||
----------
|
||||
o <http://powertweak.sourceforge.net/>
|
||||
|
||||
udev
|
||||
----
|
||||
o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
|
||||
|
@ -58,7 +58,7 @@
|
||||
</sect1>
|
||||
<sect1><title>Wait queues and Wake events</title>
|
||||
!Iinclude/linux/wait.h
|
||||
!Ekernel/wait.c
|
||||
!Ekernel/sched/wait.c
|
||||
</sect1>
|
||||
<sect1><title>High-resolution timers</title>
|
||||
!Iinclude/linux/ktime.h
|
||||
|
@ -1,7 +1,8 @@
|
||||
I2C for OMAP platforms
|
||||
|
||||
Required properties :
|
||||
- compatible : Must be "ti,omap3-i2c" or "ti,omap4-i2c"
|
||||
- compatible : Must be "ti,omap2420-i2c", "ti,omap2430-i2c", "ti,omap3-i2c"
|
||||
or "ti,omap4-i2c"
|
||||
- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
|
17
Documentation/devicetree/bindings/rng/qcom,prng.txt
Normal file
17
Documentation/devicetree/bindings/rng/qcom,prng.txt
Normal file
@ -0,0 +1,17 @@
|
||||
Qualcomm MSM pseudo random number generator.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "qcom,prng"
|
||||
- reg : specifies base physical address and size of the registers map
|
||||
- clocks : phandle to clock-controller plus clock-specifier pair
|
||||
- clock-names : "core" clocks all registers, FIFO and circuits in PRNG IP block
|
||||
|
||||
Example:
|
||||
|
||||
rng@f9bff000 {
|
||||
compatible = "qcom,prng";
|
||||
reg = <0xf9bff000 0x200>;
|
||||
clocks = <&clock GCC_PRNG_AHB_CLK>;
|
||||
clock-names = "core";
|
||||
};
|
115
Documentation/gpio/board.txt
Normal file
115
Documentation/gpio/board.txt
Normal file
@ -0,0 +1,115 @@
|
||||
GPIO Mappings
|
||||
=============
|
||||
|
||||
This document explains how GPIOs can be assigned to given devices and functions.
|
||||
Note that it only applies to the new descriptor-based interface. For a
|
||||
description of the deprecated integer-based GPIO interface please refer to
|
||||
gpio-legacy.txt (actually, there is no real mapping possible with the old
|
||||
interface; you just fetch an integer from somewhere and request the
|
||||
corresponding GPIO.
|
||||
|
||||
Platforms that make use of GPIOs must select ARCH_REQUIRE_GPIOLIB (if GPIO usage
|
||||
is mandatory) or ARCH_WANT_OPTIONAL_GPIOLIB (if GPIO support can be omitted) in
|
||||
their Kconfig. Then, how GPIOs are mapped depends on what the platform uses to
|
||||
describe its hardware layout. Currently, mappings can be defined through device
|
||||
tree, ACPI, and platform data.
|
||||
|
||||
Device Tree
|
||||
-----------
|
||||
GPIOs can easily be mapped to devices and functions in the device tree. The
|
||||
exact way to do it depends on the GPIO controller providing the GPIOs, see the
|
||||
device tree bindings for your controller.
|
||||
|
||||
GPIOs mappings are defined in the consumer device's node, in a property named
|
||||
<function>-gpios, where <function> is the function the driver will request
|
||||
through gpiod_get(). For example:
|
||||
|
||||
foo_device {
|
||||
compatible = "acme,foo";
|
||||
...
|
||||
led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
|
||||
<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
|
||||
<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
|
||||
|
||||
power-gpio = <&gpio 1 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
This property will make GPIOs 15, 16 and 17 available to the driver under the
|
||||
"led" function, and GPIO 1 as the "power" GPIO:
|
||||
|
||||
struct gpio_desc *red, *green, *blue, *power;
|
||||
|
||||
red = gpiod_get_index(dev, "led", 0);
|
||||
green = gpiod_get_index(dev, "led", 1);
|
||||
blue = gpiod_get_index(dev, "led", 2);
|
||||
|
||||
power = gpiod_get(dev, "power");
|
||||
|
||||
The led GPIOs will be active-high, while the power GPIO will be active-low (i.e.
|
||||
gpiod_is_active_low(power) will be true).
|
||||
|
||||
ACPI
|
||||
----
|
||||
ACPI does not support function names for GPIOs. Therefore, only the "idx"
|
||||
argument of gpiod_get_index() is useful to discriminate between GPIOs assigned
|
||||
to a device. The "con_id" argument can still be set for debugging purposes (it
|
||||
will appear under error messages as well as debug and sysfs nodes).
|
||||
|
||||
Platform Data
|
||||
-------------
|
||||
Finally, GPIOs can be bound to devices and functions using platform data. Board
|
||||
files that desire to do so need to include the following header:
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
GPIOs are mapped by the means of tables of lookups, containing instances of the
|
||||
gpiod_lookup structure. Two macros are defined to help declaring such mappings:
|
||||
|
||||
GPIO_LOOKUP(chip_label, chip_hwnum, dev_id, con_id, flags)
|
||||
GPIO_LOOKUP_IDX(chip_label, chip_hwnum, dev_id, con_id, idx, flags)
|
||||
|
||||
where
|
||||
|
||||
- chip_label is the label of the gpiod_chip instance providing the GPIO
|
||||
- chip_hwnum is the hardware number of the GPIO within the chip
|
||||
- dev_id is the identifier of the device that will make use of this GPIO. If
|
||||
NULL, the GPIO will be available to all devices.
|
||||
- con_id is the name of the GPIO function from the device point of view. It
|
||||
can be NULL.
|
||||
- idx is the index of the GPIO within the function.
|
||||
- flags is defined to specify the following properties:
|
||||
* GPIOF_ACTIVE_LOW - to configure the GPIO as active-low
|
||||
* GPIOF_OPEN_DRAIN - GPIO pin is open drain type.
|
||||
* GPIOF_OPEN_SOURCE - GPIO pin is open source type.
|
||||
|
||||
In the future, these flags might be extended to support more properties.
|
||||
|
||||
Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0.
|
||||
|
||||
A lookup table can then be defined as follows:
|
||||
|
||||
struct gpiod_lookup gpios_table[] = {
|
||||
GPIO_LOOKUP_IDX("gpio.0", 15, "foo.0", "led", 0, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP_IDX("gpio.0", 16, "foo.0", "led", 1, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP_IDX("gpio.0", 17, "foo.0", "led", 2, GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("gpio.0", 1, "foo.0", "power", GPIO_ACTIVE_LOW),
|
||||
};
|
||||
|
||||
And the table can be added by the board code as follows:
|
||||
|
||||
gpiod_add_table(gpios_table, ARRAY_SIZE(gpios_table));
|
||||
|
||||
The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:
|
||||
|
||||
struct gpio_desc *red, *green, *blue, *power;
|
||||
|
||||
red = gpiod_get_index(dev, "led", 0);
|
||||
green = gpiod_get_index(dev, "led", 1);
|
||||
blue = gpiod_get_index(dev, "led", 2);
|
||||
|
||||
power = gpiod_get(dev, "power");
|
||||
gpiod_direction_output(power, 1);
|
||||
|
||||
Since the "power" GPIO is mapped as active-low, its actual signal will be 0
|
||||
after this code. Contrary to the legacy integer GPIO interface, the active-low
|
||||
property is handled during mapping and is thus transparent to GPIO consumers.
|
197
Documentation/gpio/consumer.txt
Normal file
197
Documentation/gpio/consumer.txt
Normal file
@ -0,0 +1,197 @@
|
||||
GPIO Descriptor Consumer Interface
|
||||
==================================
|
||||
|
||||
This document describes the consumer interface of the GPIO framework. Note that
|
||||
it describes the new descriptor-based interface. For a description of the
|
||||
deprecated integer-based GPIO interface please refer to gpio-legacy.txt.
|
||||
|
||||
|
||||
Guidelines for GPIOs consumers
|
||||
==============================
|
||||
|
||||
Drivers that can't work without standard GPIO calls should have Kconfig entries
|
||||
that depend on GPIOLIB. The functions that allow a driver to obtain and use
|
||||
GPIOs are available by including the following file:
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
All the functions that work with the descriptor-based GPIO interface are
|
||||
prefixed with gpiod_. The gpio_ prefix is used for the legacy interface. No
|
||||
other function in the kernel should use these prefixes.
|
||||
|
||||
|
||||
Obtaining and Disposing GPIOs
|
||||
=============================
|
||||
|
||||
With the descriptor-based interface, GPIOs are identified with an opaque,
|
||||
non-forgeable handler that must be obtained through a call to one of the
|
||||
gpiod_get() functions. Like many other kernel subsystems, gpiod_get() takes the
|
||||
device that will use the GPIO and the function the requested GPIO is supposed to
|
||||
fulfill:
|
||||
|
||||
struct gpio_desc *gpiod_get(struct device *dev, const char *con_id)
|
||||
|
||||
If a function is implemented by using several GPIOs together (e.g. a simple LED
|
||||
device that displays digits), an additional index argument can be specified:
|
||||
|
||||
struct gpio_desc *gpiod_get_index(struct device *dev,
|
||||
const char *con_id, unsigned int idx)
|
||||
|
||||
Both functions return either a valid GPIO descriptor, or an error code checkable
|
||||
with IS_ERR(). They will never return a NULL pointer.
|
||||
|
||||
Device-managed variants of these functions are also defined:
|
||||
|
||||
struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id)
|
||||
|
||||
struct gpio_desc *devm_gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx)
|
||||
|
||||
A GPIO descriptor can be disposed of using the gpiod_put() function:
|
||||
|
||||
void gpiod_put(struct gpio_desc *desc)
|
||||
|
||||
It is strictly forbidden to use a descriptor after calling this function. The
|
||||
device-managed variant is, unsurprisingly:
|
||||
|
||||
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
|
||||
|
||||
|
||||
Using GPIOs
|
||||
===========
|
||||
|
||||
Setting Direction
|
||||
-----------------
|
||||
The first thing a driver must do with a GPIO is setting its direction. This is
|
||||
done by invoking one of the gpiod_direction_*() functions:
|
||||
|
||||
int gpiod_direction_input(struct gpio_desc *desc)
|
||||
int gpiod_direction_output(struct gpio_desc *desc, int value)
|
||||
|
||||
The return value is zero for success, else a negative errno. It should be
|
||||
checked, since the get/set calls don't return errors and since misconfiguration
|
||||
is possible. You should normally issue these calls from a task context. However,
|
||||
for spinlock-safe GPIOs it is OK to use them before tasking is enabled, as part
|
||||
of early board setup.
|
||||
|
||||
For output GPIOs, the value provided becomes the initial output value. This
|
||||
helps avoid signal glitching during system startup.
|
||||
|
||||
A driver can also query the current direction of a GPIO:
|
||||
|
||||
int gpiod_get_direction(const struct gpio_desc *desc)
|
||||
|
||||
This function will return either GPIOF_DIR_IN or GPIOF_DIR_OUT.
|
||||
|
||||
Be aware that there is no default direction for GPIOs. Therefore, **using a GPIO
|
||||
without setting its direction first is illegal and will result in undefined
|
||||
behavior!**
|
||||
|
||||
|
||||
Spinlock-Safe GPIO Access
|
||||
-------------------------
|
||||
Most GPIO controllers can be accessed with memory read/write instructions. Those
|
||||
don't need to sleep, and can safely be done from inside hard (non-threaded) IRQ
|
||||
handlers and similar contexts.
|
||||
|
||||
Use the following calls to access GPIOs from an atomic context:
|
||||
|
||||
int gpiod_get_value(const struct gpio_desc *desc);
|
||||
void gpiod_set_value(struct gpio_desc *desc, int value);
|
||||
|
||||
The values are boolean, zero for low, nonzero for high. When reading the value
|
||||
of an output pin, the value returned should be what's seen on the pin. That
|
||||
won't always match the specified output value, because of issues including
|
||||
open-drain signaling and output latencies.
|
||||
|
||||
The get/set calls do not return errors because "invalid GPIO" should have been
|
||||
reported earlier from gpiod_direction_*(). However, note that not all platforms
|
||||
can read the value of output pins; those that can't should always return zero.
|
||||
Also, using these calls for GPIOs that can't safely be accessed without sleeping
|
||||
(see below) is an error.
|
||||
|
||||
|
||||
GPIO Access That May Sleep
|
||||
--------------------------
|
||||
Some GPIO controllers must be accessed using message based buses like I2C or
|
||||
SPI. Commands to read or write those GPIO values require waiting to get to the
|
||||
head of a queue to transmit a command and get its response. This requires
|
||||
sleeping, which can't be done from inside IRQ handlers.
|
||||
|
||||
Platforms that support this type of GPIO distinguish them from other GPIOs by
|
||||
returning nonzero from this call:
|
||||
|
||||
int gpiod_cansleep(const struct gpio_desc *desc)
|
||||
|
||||
To access such GPIOs, a different set of accessors is defined:
|
||||
|
||||
int gpiod_get_value_cansleep(const struct gpio_desc *desc)
|
||||
void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
|
||||
|
||||
Accessing such GPIOs requires a context which may sleep, for example a threaded
|
||||
IRQ handler, and those accessors must be used instead of spinlock-safe
|
||||
accessors without the cansleep() name suffix.
|
||||
|
||||
Other than the fact that these accessors might sleep, and will work on GPIOs
|
||||
that can't be accessed from hardIRQ handlers, these calls act the same as the
|
||||
spinlock-safe calls.
|
||||
|
||||
|
||||
Active-low State and Raw GPIO Values
|
||||
------------------------------------
|
||||
Device drivers like to manage the logical state of a GPIO, i.e. the value their
|
||||
device will actually receive, no matter what lies between it and the GPIO line.
|
||||
In some cases, it might make sense to control the actual GPIO line value. The
|
||||
following set of calls ignore the active-low property of a GPIO and work on the
|
||||
raw line value:
|
||||
|
||||
int gpiod_get_raw_value(const struct gpio_desc *desc)
|
||||
void gpiod_set_raw_value(struct gpio_desc *desc, int value)
|
||||
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
|
||||
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
|
||||
|
||||
The active-low state of a GPIO can also be queried using the following call:
|
||||
|
||||
int gpiod_is_active_low(const struct gpio_desc *desc)
|
||||
|
||||
Note that these functions should only be used with great moderation ; a driver
|
||||
should not have to care about the physical line level.
|
||||
|
||||
GPIOs mapped to IRQs
|
||||
--------------------
|
||||
GPIO lines can quite often be used as IRQs. You can get the IRQ number
|
||||
corresponding to a given GPIO using the following call:
|
||||
|
||||
int gpiod_to_irq(const struct gpio_desc *desc)
|
||||
|
||||
It will return an IRQ number, or an negative errno code if the mapping can't be
|
||||
done (most likely because that particular GPIO cannot be used as IRQ). It is an
|
||||
unchecked error to use a GPIO that wasn't set up as an input using
|
||||
gpiod_direction_input(), or to use an IRQ number that didn't originally come
|
||||
from gpiod_to_irq(). gpiod_to_irq() is not allowed to sleep.
|
||||
|
||||
Non-error values returned from gpiod_to_irq() can be passed to request_irq() or
|
||||
free_irq(). They will often be stored into IRQ resources for platform devices,
|
||||
by the board-specific initialization code. Note that IRQ trigger options are
|
||||
part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are system wakeup
|
||||
capabilities.
|
||||
|
||||
|
||||
Interacting With the Legacy GPIO Subsystem
|
||||
==========================================
|
||||
Many kernel subsystems still handle GPIOs using the legacy integer-based
|
||||
interface. Although it is strongly encouraged to upgrade them to the safer
|
||||
descriptor-based API, the following two functions allow you to convert a GPIO
|
||||
descriptor into the GPIO integer namespace and vice-versa:
|
||||
|
||||
int desc_to_gpio(const struct gpio_desc *desc)
|
||||
struct gpio_desc *gpio_to_desc(unsigned gpio)
|
||||
|
||||
The GPIO number returned by desc_to_gpio() can be safely used as long as the
|
||||
GPIO descriptor has not been freed. All the same, a GPIO number passed to
|
||||
gpio_to_desc() must have been properly acquired, and usage of the returned GPIO
|
||||
descriptor is only possible after the GPIO number has been released.
|
||||
|
||||
Freeing a GPIO obtained by one API with the other API is forbidden and an
|
||||
unchecked error.
|
75
Documentation/gpio/driver.txt
Normal file
75
Documentation/gpio/driver.txt
Normal file
@ -0,0 +1,75 @@
|
||||
GPIO Descriptor Driver Interface
|
||||
================================
|
||||
|
||||
This document serves as a guide for GPIO chip drivers writers. Note that it
|
||||
describes the new descriptor-based interface. For a description of the
|
||||
deprecated integer-based GPIO interface please refer to gpio-legacy.txt.
|
||||
|
||||
Each GPIO controller driver needs to include the following header, which defines
|
||||
the structures used to define a GPIO driver:
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
|
||||
Internal Representation of GPIOs
|
||||
================================
|
||||
|
||||
Inside a GPIO driver, individual GPIOs are identified by their hardware number,
|
||||
which is a unique number between 0 and n, n being the number of GPIOs managed by
|
||||
the chip. This number is purely internal: the hardware number of a particular
|
||||
GPIO descriptor is never made visible outside of the driver.
|
||||
|
||||
On top of this internal number, each GPIO also need to have a global number in
|
||||
the integer GPIO namespace so that it can be used with the legacy GPIO
|
||||
interface. Each chip must thus have a "base" number (which can be automatically
|
||||
assigned), and for each GPIO the global number will be (base + hardware number).
|
||||
Although the integer representation is considered deprecated, it still has many
|
||||
users and thus needs to be maintained.
|
||||
|
||||
So for example one platform could use numbers 32-159 for GPIOs, with a
|
||||
controller defining 128 GPIOs at a "base" of 32 ; while another platform uses
|
||||
numbers 0..63 with one set of GPIO controllers, 64-79 with another type of GPIO
|
||||
controller, and on one particular board 80-95 with an FPGA. The numbers need not
|
||||
be contiguous; either of those platforms could also use numbers 2000-2063 to
|
||||
identify GPIOs in a bank of I2C GPIO expanders.
|
||||
|
||||
|
||||
Controller Drivers: gpio_chip
|
||||
=============================
|
||||
|
||||
In the gpiolib framework each GPIO controller is packaged as a "struct
|
||||
gpio_chip" (see linux/gpio/driver.h for its complete definition) with members
|
||||
common to each controller of that type:
|
||||
|
||||
- methods to establish GPIO direction
|
||||
- methods used to access GPIO values
|
||||
- method to return the IRQ number associated to a given GPIO
|
||||
- flag saying whether calls to its methods may sleep
|
||||
- optional debugfs dump method (showing extra state like pullup config)
|
||||
- optional base number (will be automatically assigned if omitted)
|
||||
- label for diagnostics and GPIOs mapping using platform data
|
||||
|
||||
The code implementing a gpio_chip should support multiple instances of the
|
||||
controller, possibly using the driver model. That code will configure each
|
||||
gpio_chip and issue gpiochip_add(). Removing a GPIO controller should be rare;
|
||||
use gpiochip_remove() when it is unavoidable.
|
||||
|
||||
Most often a gpio_chip is part of an instance-specific structure with state not
|
||||
exposed by the GPIO interfaces, such as addressing, power management, and more.
|
||||
Chips such as codecs will have complex non-GPIO state.
|
||||
|
||||
Any debugfs dump method should normally ignore signals which haven't been
|
||||
requested as GPIOs. They can use gpiochip_is_requested(), which returns either
|
||||
NULL or the label associated with that GPIO when it was requested.
|
||||
|
||||
Locking IRQ usage
|
||||
-----------------
|
||||
Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
|
||||
to mark the GPIO as being used as an IRQ:
|
||||
|
||||
int gpiod_lock_as_irq(struct gpio_desc *desc)
|
||||
|
||||
This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
|
||||
is released:
|
||||
|
||||
void gpiod_unlock_as_irq(struct gpio_desc *desc)
|
119
Documentation/gpio/gpio.txt
Normal file
119
Documentation/gpio/gpio.txt
Normal file
@ -0,0 +1,119 @@
|
||||
GPIO Interfaces
|
||||
===============
|
||||
|
||||
The documents in this directory give detailed instructions on how to access
|
||||
GPIOs in drivers, and how to write a driver for a device that provides GPIOs
|
||||
itself.
|
||||
|
||||
Due to the history of GPIO interfaces in the kernel, there are two different
|
||||
ways to obtain and use GPIOs:
|
||||
|
||||
- The descriptor-based interface is the preferred way to manipulate GPIOs,
|
||||
and is described by all the files in this directory excepted gpio-legacy.txt.
|
||||
- The legacy integer-based interface which is considered deprecated (but still
|
||||
usable for compatibility reasons) is documented in gpio-legacy.txt.
|
||||
|
||||
The remainder of this document applies to the new descriptor-based interface.
|
||||
gpio-legacy.txt contains the same information applied to the legacy
|
||||
integer-based interface.
|
||||
|
||||
|
||||
What is a GPIO?
|
||||
===============
|
||||
|
||||
A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
|
||||
digital signal. They are provided from many kinds of chip, and are familiar
|
||||
to Linux developers working with embedded and custom hardware. Each GPIO
|
||||
represents a bit connected to a particular pin, or "ball" on Ball Grid Array
|
||||
(BGA) packages. Board schematics show which external hardware connects to
|
||||
which GPIOs. Drivers can be written generically, so that board setup code
|
||||
passes such pin configuration data to drivers.
|
||||
|
||||
System-on-Chip (SOC) processors heavily rely on GPIOs. In some cases, every
|
||||
non-dedicated pin can be configured as a GPIO; and most chips have at least
|
||||
several dozen of them. Programmable logic devices (like FPGAs) can easily
|
||||
provide GPIOs; multifunction chips like power managers, and audio codecs
|
||||
often have a few such pins to help with pin scarcity on SOCs; and there are
|
||||
also "GPIO Expander" chips that connect using the I2C or SPI serial buses.
|
||||
Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
|
||||
firmware knowing how they're used).
|
||||
|
||||
The exact capabilities of GPIOs vary between systems. Common options:
|
||||
|
||||
- Output values are writable (high=1, low=0). Some chips also have
|
||||
options about how that value is driven, so that for example only one
|
||||
value might be driven, supporting "wire-OR" and similar schemes for the
|
||||
other value (notably, "open drain" signaling).
|
||||
|
||||
- Input values are likewise readable (1, 0). Some chips support readback
|
||||
of pins configured as "output", which is very useful in such "wire-OR"
|
||||
cases (to support bidirectional signaling). GPIO controllers may have
|
||||
input de-glitch/debounce logic, sometimes with software controls.
|
||||
|
||||
- Inputs can often be used as IRQ signals, often edge triggered but
|
||||
sometimes level triggered. Such IRQs may be configurable as system
|
||||
wakeup events, to wake the system from a low power state.
|
||||
|
||||
- Usually a GPIO will be configurable as either input or output, as needed
|
||||
by different product boards; single direction ones exist too.
|
||||
|
||||
- Most GPIOs can be accessed while holding spinlocks, but those accessed
|
||||
through a serial bus normally can't. Some systems support both types.
|
||||
|
||||
On a given board each GPIO is used for one specific purpose like monitoring
|
||||
MMC/SD card insertion/removal, detecting card write-protect status, driving
|
||||
a LED, configuring a transceiver, bit-banging a serial bus, poking a hardware
|
||||
watchdog, sensing a switch, and so on.
|
||||
|
||||
|
||||
Common GPIO Properties
|
||||
======================
|
||||
|
||||
These properties are met through all the other documents of the GPIO interface
|
||||
and it is useful to understand them, especially if you need to define GPIO
|
||||
mappings.
|
||||
|
||||
Active-High and Active-Low
|
||||
--------------------------
|
||||
It is natural to assume that a GPIO is "active" when its output signal is 1
|
||||
("high"), and inactive when it is 0 ("low"). However in practice the signal of a
|
||||
GPIO may be inverted before is reaches its destination, or a device could decide
|
||||
to have different conventions about what "active" means. Such decisions should
|
||||
be transparent to device drivers, therefore it is possible to define a GPIO as
|
||||
being either active-high ("1" means "active", the default) or active-low ("0"
|
||||
means "active") so that drivers only need to worry about the logical signal and
|
||||
not about what happens at the line level.
|
||||
|
||||
Open Drain and Open Source
|
||||
--------------------------
|
||||
Sometimes shared signals need to use "open drain" (where only the low signal
|
||||
level is actually driven), or "open source" (where only the high signal level is
|
||||
driven) signaling. That term applies to CMOS transistors; "open collector" is
|
||||
used for TTL. A pullup or pulldown resistor causes the high or low signal level.
|
||||
This is sometimes called a "wire-AND"; or more practically, from the negative
|
||||
logic (low=true) perspective this is a "wire-OR".
|
||||
|
||||
One common example of an open drain signal is a shared active-low IRQ line.
|
||||
Also, bidirectional data bus signals sometimes use open drain signals.
|
||||
|
||||
Some GPIO controllers directly support open drain and open source outputs; many
|
||||
don't. When you need open drain signaling but your hardware doesn't directly
|
||||
support it, there's a common idiom you can use to emulate it with any GPIO pin
|
||||
that can be used as either an input or an output:
|
||||
|
||||
LOW: gpiod_direction_output(gpio, 0) ... this drives the signal and overrides
|
||||
the pullup.
|
||||
|
||||
HIGH: gpiod_direction_input(gpio) ... this turns off the output, so the pullup
|
||||
(or some other device) controls the signal.
|
||||
|
||||
The same logic can be applied to emulate open source signaling, by driving the
|
||||
high signal and configuring the GPIO as input for low. This open drain/open
|
||||
source emulation can be handled transparently by the GPIO framework.
|
||||
|
||||
If you are "driving" the signal high but gpiod_get_value(gpio) reports a low
|
||||
value (after the appropriate rise time passes), you know some other component is
|
||||
driving the shared signal low. That's not necessarily an error. As one common
|
||||
example, that's how I2C clocks are stretched: a slave that needs a slower clock
|
||||
delays the rising edge of SCK, and the I2C master adjusts its signaling rate
|
||||
accordingly.
|
155
Documentation/gpio/sysfs.txt
Normal file
155
Documentation/gpio/sysfs.txt
Normal file
@ -0,0 +1,155 @@
|
||||
GPIO Sysfs Interface for Userspace
|
||||
==================================
|
||||
|
||||
Platforms which use the "gpiolib" implementors framework may choose to
|
||||
configure a sysfs user interface to GPIOs. This is different from the
|
||||
debugfs interface, since it provides control over GPIO direction and
|
||||
value instead of just showing a gpio state summary. Plus, it could be
|
||||
present on production systems without debugging support.
|
||||
|
||||
Given appropriate hardware documentation for the system, userspace could
|
||||
know for example that GPIO #23 controls the write protect line used to
|
||||
protect boot loader segments in flash memory. System upgrade procedures
|
||||
may need to temporarily remove that protection, first importing a GPIO,
|
||||
then changing its output state, then updating the code before re-enabling
|
||||
the write protection. In normal use, GPIO #23 would never be touched,
|
||||
and the kernel would have no need to know about it.
|
||||
|
||||
Again depending on appropriate hardware documentation, on some systems
|
||||
userspace GPIO can be used to determine system configuration data that
|
||||
standard kernels won't know about. And for some tasks, simple userspace
|
||||
GPIO drivers could be all that the system really needs.
|
||||
|
||||
Note that standard kernel drivers exist for common "LEDs and Buttons"
|
||||
GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
|
||||
instead of talking directly to the GPIOs; they integrate with kernel
|
||||
frameworks better than your userspace code could.
|
||||
|
||||
|
||||
Paths in Sysfs
|
||||
--------------
|
||||
There are three kinds of entry in /sys/class/gpio:
|
||||
|
||||
- Control interfaces used to get userspace control over GPIOs;
|
||||
|
||||
- GPIOs themselves; and
|
||||
|
||||
- GPIO controllers ("gpio_chip" instances).
|
||||
|
||||
That's in addition to standard files including the "device" symlink.
|
||||
|
||||
The control interfaces are write-only:
|
||||
|
||||
/sys/class/gpio/
|
||||
|
||||
"export" ... Userspace may ask the kernel to export control of
|
||||
a GPIO to userspace by writing its number to this file.
|
||||
|
||||
Example: "echo 19 > export" will create a "gpio19" node
|
||||
for GPIO #19, if that's not requested by kernel code.
|
||||
|
||||
"unexport" ... Reverses the effect of exporting to userspace.
|
||||
|
||||
Example: "echo 19 > unexport" will remove a "gpio19"
|
||||
node exported using the "export" file.
|
||||
|
||||
GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
|
||||
and have the following read/write attributes:
|
||||
|
||||
/sys/class/gpio/gpioN/
|
||||
|
||||
"direction" ... reads as either "in" or "out". This value may
|
||||
normally be written. Writing as "out" defaults to
|
||||
initializing the value as low. To ensure glitch free
|
||||
operation, values "low" and "high" may be written to
|
||||
configure the GPIO as an output with that initial value.
|
||||
|
||||
Note that this attribute *will not exist* if the kernel
|
||||
doesn't support changing the direction of a GPIO, or
|
||||
it was exported by kernel code that didn't explicitly
|
||||
allow userspace to reconfigure this GPIO's direction.
|
||||
|
||||
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
|
||||
is configured as an output, this value may be written;
|
||||
any nonzero value is treated as high.
|
||||
|
||||
If the pin can be configured as interrupt-generating interrupt
|
||||
and if it has been configured to generate interrupts (see the
|
||||
description of "edge"), you can poll(2) on that file and
|
||||
poll(2) will return whenever the interrupt was triggered. If
|
||||
you use poll(2), set the events POLLPRI and POLLERR. If you
|
||||
use select(2), set the file descriptor in exceptfds. After
|
||||
poll(2) returns, either lseek(2) to the beginning of the sysfs
|
||||
file and read the new value or close the file and re-open it
|
||||
to read the value.
|
||||
|
||||
"edge" ... reads as either "none", "rising", "falling", or
|
||||
"both". Write these strings to select the signal edge(s)
|
||||
that will make poll(2) on the "value" file return.
|
||||
|
||||
This file exists only if the pin can be configured as an
|
||||
interrupt generating input pin.
|
||||
|
||||
"active_low" ... reads as either 0 (false) or 1 (true). Write
|
||||
any nonzero value to invert the value attribute both
|
||||
for reading and writing. Existing and subsequent
|
||||
poll(2) support configuration via the edge attribute
|
||||
for "rising" and "falling" edges will follow this
|
||||
setting.
|
||||
|
||||
GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
|
||||
controller implementing GPIOs starting at #42) and have the following
|
||||
read-only attributes:
|
||||
|
||||
/sys/class/gpio/gpiochipN/
|
||||
|
||||
"base" ... same as N, the first GPIO managed by this chip
|
||||
|
||||
"label" ... provided for diagnostics (not always unique)
|
||||
|
||||
"ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
|
||||
|
||||
Board documentation should in most cases cover what GPIOs are used for
|
||||
what purposes. However, those numbers are not always stable; GPIOs on
|
||||
a daughtercard might be different depending on the base board being used,
|
||||
or other cards in the stack. In such cases, you may need to use the
|
||||
gpiochip nodes (possibly in conjunction with schematics) to determine
|
||||
the correct GPIO number to use for a given signal.
|
||||
|
||||
|
||||
Exporting from Kernel code
|
||||
--------------------------
|
||||
Kernel code can explicitly manage exports of GPIOs which have already been
|
||||
requested using gpio_request():
|
||||
|
||||
/* export the GPIO to userspace */
|
||||
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
|
||||
|
||||
/* reverse gpio_export() */
|
||||
void gpiod_unexport(struct gpio_desc *desc);
|
||||
|
||||
/* create a sysfs link to an exported GPIO node */
|
||||
int gpiod_export_link(struct device *dev, const char *name,
|
||||
struct gpio_desc *desc);
|
||||
|
||||
/* change the polarity of a GPIO node in sysfs */
|
||||
int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
|
||||
|
||||
After a kernel driver requests a GPIO, it may only be made available in
|
||||
the sysfs interface by gpiod_export(). The driver can control whether the
|
||||
signal direction may change. This helps drivers prevent userspace code
|
||||
from accidentally clobbering important system state.
|
||||
|
||||
This explicit exporting can help with debugging (by making some kinds
|
||||
of experiments easier), or can provide an always-there interface that's
|
||||
suitable for documenting as part of a board support package.
|
||||
|
||||
After the GPIO has been exported, gpiod_export_link() allows creating
|
||||
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
|
||||
use this to provide the interface under their own device in sysfs with
|
||||
a descriptive name.
|
||||
|
||||
Drivers can use gpiod_sysfs_set_active_low() to hide GPIO line polarity
|
||||
differences between boards from user space. Polarity change can be done both
|
||||
before and after gpiod_export(), and previously enabled poll(2) support for
|
||||
either rising or falling edge will be reconfigured to follow this setting.
|
@ -2142,6 +2142,11 @@ L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/usb/chipidea/
|
||||
|
||||
CHROME HARDWARE PLATFORM SUPPORT
|
||||
M: Olof Johansson <olof@lixom.net>
|
||||
S: Maintained
|
||||
F: drivers/platform/chrome/
|
||||
|
||||
CISCO VIC ETHERNET NIC DRIVER
|
||||
M: Christian Benvenuti <benve@cisco.com>
|
||||
M: Sujith Sankar <ssujith@cisco.com>
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 3
|
||||
PATCHLEVEL = 13
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = One Giant Leap for Frogkind
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -85,6 +85,8 @@
|
||||
reg = <0x7e205000 0x1000>;
|
||||
interrupts = <2 21>;
|
||||
clocks = <&clk_i2c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@ -93,6 +95,8 @@
|
||||
reg = <0x7e804000 0x1000>;
|
||||
interrupts = <2 21>;
|
||||
clocks = <&clk_i2c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,13 @@
|
||||
i2c2_bus: i2c2-bus {
|
||||
samsung,pin-pud = <0>;
|
||||
};
|
||||
|
||||
max77686_irq: max77686-irq {
|
||||
samsung,pins = "gpx3-2";
|
||||
samsung,pin-function = <0>;
|
||||
samsung,pin-pud = <0>;
|
||||
samsung,pin-drv = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@12C60000 {
|
||||
@ -35,6 +42,11 @@
|
||||
|
||||
max77686@09 {
|
||||
compatible = "maxim,max77686";
|
||||
interrupt-parent = <&gpx3>;
|
||||
interrupts = <2 0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&max77686_irq>;
|
||||
wakeup-source;
|
||||
reg = <0x09>;
|
||||
|
||||
voltage-regulators {
|
||||
|
@ -161,7 +161,7 @@
|
||||
clocks = <&clks 197>, <&clks 3>,
|
||||
<&clks 197>, <&clks 107>,
|
||||
<&clks 0>, <&clks 118>,
|
||||
<&clks 62>, <&clks 139>,
|
||||
<&clks 0>, <&clks 139>,
|
||||
<&clks 0>;
|
||||
clock-names = "core", "rxtx0",
|
||||
"rxtx1", "rxtx2",
|
||||
|
@ -13,7 +13,7 @@
|
||||
* they probably share the same GPIO IRQ
|
||||
* REVISIT: Add timing support from slls644g.pdf
|
||||
*/
|
||||
8250@3,0 {
|
||||
uart@3,0 {
|
||||
compatible = "ns16550a";
|
||||
reg = <3 0 0x100>;
|
||||
bank-width = <2>;
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/pinctrl/omap.h>
|
||||
|
||||
#include "skeleton.dtsi"
|
||||
@ -21,6 +22,8 @@
|
||||
serial0 = &uart1;
|
||||
serial1 = &uart2;
|
||||
serial2 = &uart3;
|
||||
i2c0 = &i2c1;
|
||||
i2c1 = &i2c2;
|
||||
};
|
||||
|
||||
cpus {
|
||||
@ -53,6 +56,28 @@
|
||||
ranges;
|
||||
ti,hwmods = "l3_main";
|
||||
|
||||
aes: aes@480a6000 {
|
||||
compatible = "ti,omap2-aes";
|
||||
ti,hwmods = "aes";
|
||||
reg = <0x480a6000 0x50>;
|
||||
dmas = <&sdma 9 &sdma 10>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
hdq1w: 1w@480b2000 {
|
||||
compatible = "ti,omap2420-1w";
|
||||
ti,hwmods = "hdq1w";
|
||||
reg = <0x480b2000 0x1000>;
|
||||
interrupts = <58>;
|
||||
};
|
||||
|
||||
mailbox: mailbox@48094000 {
|
||||
compatible = "ti,omap2-mailbox";
|
||||
ti,hwmods = "mailbox";
|
||||
reg = <0x48094000 0x200>;
|
||||
interrupts = <26>;
|
||||
};
|
||||
|
||||
intc: interrupt-controller@1 {
|
||||
compatible = "ti,omap2-intc";
|
||||
interrupt-controller;
|
||||
@ -63,6 +88,7 @@
|
||||
|
||||
sdma: dma-controller@48056000 {
|
||||
compatible = "ti,omap2430-sdma", "ti,omap2420-sdma";
|
||||
ti,hwmods = "dma";
|
||||
reg = <0x48056000 0x1000>;
|
||||
interrupts = <12>,
|
||||
<13>,
|
||||
@ -73,21 +99,91 @@
|
||||
#dma-requests = <64>;
|
||||
};
|
||||
|
||||
i2c1: i2c@48070000 {
|
||||
compatible = "ti,omap2-i2c";
|
||||
ti,hwmods = "i2c1";
|
||||
reg = <0x48070000 0x80>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <56>;
|
||||
dmas = <&sdma 27 &sdma 28>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
i2c2: i2c@48072000 {
|
||||
compatible = "ti,omap2-i2c";
|
||||
ti,hwmods = "i2c2";
|
||||
reg = <0x48072000 0x80>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <57>;
|
||||
dmas = <&sdma 29 &sdma 30>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
mcspi1: mcspi@48098000 {
|
||||
compatible = "ti,omap2-mcspi";
|
||||
ti,hwmods = "mcspi1";
|
||||
reg = <0x48098000 0x100>;
|
||||
interrupts = <65>;
|
||||
dmas = <&sdma 35 &sdma 36 &sdma 37 &sdma 38
|
||||
&sdma 39 &sdma 40 &sdma 41 &sdma 42>;
|
||||
dma-names = "tx0", "rx0", "tx1", "rx1",
|
||||
"tx2", "rx2", "tx3", "rx3";
|
||||
};
|
||||
|
||||
mcspi2: mcspi@4809a000 {
|
||||
compatible = "ti,omap2-mcspi";
|
||||
ti,hwmods = "mcspi2";
|
||||
reg = <0x4809a000 0x100>;
|
||||
interrupts = <66>;
|
||||
dmas = <&sdma 43 &sdma 44 &sdma 45 &sdma 46>;
|
||||
dma-names = "tx0", "rx0", "tx1", "rx1";
|
||||
};
|
||||
|
||||
rng: rng@480a0000 {
|
||||
compatible = "ti,omap2-rng";
|
||||
ti,hwmods = "rng";
|
||||
reg = <0x480a0000 0x50>;
|
||||
interrupts = <36>;
|
||||
};
|
||||
|
||||
sham: sham@480a4000 {
|
||||
compatible = "ti,omap2-sham";
|
||||
ti,hwmods = "sham";
|
||||
reg = <0x480a4000 0x64>;
|
||||
interrupts = <51>;
|
||||
dmas = <&sdma 13>;
|
||||
dma-names = "rx";
|
||||
};
|
||||
|
||||
uart1: serial@4806a000 {
|
||||
compatible = "ti,omap2-uart";
|
||||
ti,hwmods = "uart1";
|
||||
reg = <0x4806a000 0x2000>;
|
||||
interrupts = <72>;
|
||||
dmas = <&sdma 49 &sdma 50>;
|
||||
dma-names = "tx", "rx";
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
|
||||
uart2: serial@4806c000 {
|
||||
compatible = "ti,omap2-uart";
|
||||
ti,hwmods = "uart2";
|
||||
reg = <0x4806c000 0x400>;
|
||||
interrupts = <73>;
|
||||
dmas = <&sdma 51 &sdma 52>;
|
||||
dma-names = "tx", "rx";
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
|
||||
uart3: serial@4806e000 {
|
||||
compatible = "ti,omap2-uart";
|
||||
ti,hwmods = "uart3";
|
||||
reg = <0x4806e000 0x400>;
|
||||
interrupts = <74>;
|
||||
dmas = <&sdma 53 &sdma 54>;
|
||||
dma-names = "tx", "rx";
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
|
||||
|
@ -114,6 +114,15 @@
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
msdi1: mmc@4809c000 {
|
||||
compatible = "ti,omap2420-mmc";
|
||||
ti,hwmods = "msdi1";
|
||||
reg = <0x4809c000 0x80>;
|
||||
interrupts = <83>;
|
||||
dmas = <&sdma 61 &sdma 62>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
timer1: timer@48028000 {
|
||||
compatible = "ti,omap2420-timer";
|
||||
reg = <0x48028000 0x400>;
|
||||
@ -121,5 +130,19 @@
|
||||
ti,hwmods = "timer1";
|
||||
ti,timer-alwon;
|
||||
};
|
||||
|
||||
wd_timer2: wdt@48022000 {
|
||||
compatible = "ti,omap2-wdt";
|
||||
ti,hwmods = "wd_timer2";
|
||||
reg = <0x48022000 0x80>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
compatible = "ti,omap2420-i2c";
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
compatible = "ti,omap2420-i2c";
|
||||
};
|
||||
|
@ -175,6 +175,25 @@
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
mmc1: mmc@4809c000 {
|
||||
compatible = "ti,omap2-hsmmc";
|
||||
reg = <0x4809c000 0x200>;
|
||||
interrupts = <83>;
|
||||
ti,hwmods = "mmc1";
|
||||
ti,dual-volt;
|
||||
dmas = <&sdma 61>, <&sdma 62>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
mmc2: mmc@480b4000 {
|
||||
compatible = "ti,omap2-hsmmc";
|
||||
reg = <0x480b4000 0x200>;
|
||||
interrupts = <86>;
|
||||
ti,hwmods = "mmc2";
|
||||
dmas = <&sdma 47>, <&sdma 48>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
timer1: timer@49018000 {
|
||||
compatible = "ti,omap2420-timer";
|
||||
reg = <0x49018000 0x400>;
|
||||
@ -182,5 +201,35 @@
|
||||
ti,hwmods = "timer1";
|
||||
ti,timer-alwon;
|
||||
};
|
||||
|
||||
mcspi3: mcspi@480b8000 {
|
||||
compatible = "ti,omap2-mcspi";
|
||||
ti,hwmods = "mcspi3";
|
||||
reg = <0x480b8000 0x100>;
|
||||
interrupts = <91>;
|
||||
dmas = <&sdma 15 &sdma 16 &sdma 23 &sdma 24>;
|
||||
dma-names = "tx0", "rx0", "tx1", "rx1";
|
||||
};
|
||||
|
||||
usb_otg_hs: usb_otg_hs@480ac000 {
|
||||
compatible = "ti,omap2-musb";
|
||||
ti,hwmods = "usb_otg_hs";
|
||||
reg = <0x480ac000 0x1000>;
|
||||
interrupts = <93>;
|
||||
};
|
||||
|
||||
wd_timer2: wdt@49016000 {
|
||||
compatible = "ti,omap2-wdt";
|
||||
ti,hwmods = "wd_timer2";
|
||||
reg = <0x49016000 0x80>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
compatible = "ti,omap2430-i2c";
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
compatible = "ti,omap2430-i2c";
|
||||
};
|
||||
|
@ -19,11 +19,11 @@ secure-common = omap-smc.o omap-secure.o
|
||||
|
||||
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
|
||||
obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
|
||||
obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
|
||||
obj-$(CONFIG_ARCH_OMAP4) += $(hwmod-common) $(secure-common)
|
||||
obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
|
||||
obj-$(CONFIG_SOC_OMAP5) += prm44xx.o $(hwmod-common) $(secure-common)
|
||||
obj-$(CONFIG_SOC_OMAP5) += $(hwmod-common) $(secure-common)
|
||||
obj-$(CONFIG_SOC_AM43XX) += $(hwmod-common) $(secure-common)
|
||||
obj-$(CONFIG_SOC_DRA7XX) += prm44xx.o $(hwmod-common) $(secure-common)
|
||||
obj-$(CONFIG_SOC_DRA7XX) += $(hwmod-common) $(secure-common)
|
||||
|
||||
ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
|
||||
obj-y += mcbsp.o
|
||||
|
@ -299,7 +299,6 @@ struct omap_sdrc_params;
|
||||
extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
|
||||
struct omap_sdrc_params *sdrc_cs1);
|
||||
struct omap2_hsmmc_info;
|
||||
extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
|
||||
extern void omap_reserve(void);
|
||||
|
||||
struct omap_hwmod;
|
||||
|
@ -32,7 +32,6 @@
|
||||
|
||||
#include "soc.h"
|
||||
#include "iomap.h"
|
||||
#include "mux.h"
|
||||
#include "control.h"
|
||||
#include "display.h"
|
||||
#include "prm.h"
|
||||
@ -102,90 +101,13 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
|
||||
{ "dss_hdmi", "omapdss_hdmi", -1 },
|
||||
};
|
||||
|
||||
static void __init omap4_tpd12s015_mux_pads(void)
|
||||
{
|
||||
omap_mux_init_signal("hdmi_cec",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_ddc_scl",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_ddc_sda",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
}
|
||||
|
||||
static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
|
||||
{
|
||||
u32 reg;
|
||||
u16 control_i2c_1;
|
||||
|
||||
/*
|
||||
* CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
|
||||
* HDMI_DDC_SCL_PULLUPRESX (bit 24) are set to disable
|
||||
* internal pull up resistor.
|
||||
*/
|
||||
if (flags & OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP) {
|
||||
control_i2c_1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1;
|
||||
reg = omap4_ctrl_pad_readl(control_i2c_1);
|
||||
reg |= (OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK |
|
||||
OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK);
|
||||
omap4_ctrl_pad_writel(reg, control_i2c_1);
|
||||
}
|
||||
}
|
||||
|
||||
static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
|
||||
{
|
||||
u32 enable_mask, enable_shift;
|
||||
u32 pipd_mask, pipd_shift;
|
||||
u32 reg;
|
||||
|
||||
if (dsi_id == 0) {
|
||||
enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
|
||||
enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
|
||||
pipd_mask = OMAP4_DSI1_PIPD_MASK;
|
||||
pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
|
||||
} else if (dsi_id == 1) {
|
||||
enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
|
||||
enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
|
||||
pipd_mask = OMAP4_DSI2_PIPD_MASK;
|
||||
pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
|
||||
|
||||
reg &= ~enable_mask;
|
||||
reg &= ~pipd_mask;
|
||||
|
||||
reg |= (lanes << enable_shift) & enable_mask;
|
||||
reg |= (lanes << pipd_shift) & pipd_mask;
|
||||
|
||||
omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init omap_hdmi_init(enum omap_hdmi_flags flags)
|
||||
{
|
||||
if (cpu_is_omap44xx()) {
|
||||
omap4_hdmi_mux_pads(flags);
|
||||
omap4_tpd12s015_mux_pads();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
return omap4_dsi_mux_pads(dsi_id, lane_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
omap4_dsi_mux_pads(dsi_id, 0);
|
||||
}
|
||||
|
||||
static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput)
|
||||
|
@ -1501,6 +1501,22 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* For some GPMC devices we still need to rely on the bootloader
|
||||
* timings because the devices can be connected via FPGA. So far
|
||||
* the list is smc91x on the omap2 SDP boards, and 8250 on zooms.
|
||||
* REVISIT: Add timing support from slls644g.pdf and from the
|
||||
* lan91c96 manual.
|
||||
*/
|
||||
if (of_device_is_compatible(child, "ns16550a") ||
|
||||
of_device_is_compatible(child, "smsc,lan91c94") ||
|
||||
of_device_is_compatible(child, "smsc,lan91c111")) {
|
||||
dev_warn(&pdev->dev,
|
||||
"%s using bootloader timings on CS%d\n",
|
||||
child->name, cs);
|
||||
goto no_timings;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: gpmc_cs_request() will map the CS to an arbitary
|
||||
* location in the gpmc address space. When booting with
|
||||
@ -1529,6 +1545,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
|
||||
gpmc_read_timings_dt(child, &gpmc_t);
|
||||
gpmc_cs_set_timings(cs, &gpmc_t);
|
||||
|
||||
no_timings:
|
||||
if (of_platform_device_create(child, NULL, &pdev->dev))
|
||||
return 0;
|
||||
|
||||
@ -1541,42 +1558,6 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* REVISIT: Add timing support from slls644g.pdf
|
||||
*/
|
||||
static int gpmc_probe_8250(struct platform_device *pdev,
|
||||
struct device_node *child)
|
||||
{
|
||||
struct resource res;
|
||||
unsigned long base;
|
||||
int ret, cs;
|
||||
|
||||
if (of_property_read_u32(child, "reg", &cs) < 0) {
|
||||
dev_err(&pdev->dev, "%s has no 'reg' property\n",
|
||||
child->full_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_address_to_resource(child, 0, &res) < 0) {
|
||||
dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
|
||||
child->full_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpmc_cs_request(cs, resource_size(&res), &base);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (of_platform_device_create(child, NULL, &pdev->dev))
|
||||
return 0;
|
||||
|
||||
dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int gpmc_probe_dt(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
@ -1618,10 +1599,9 @@ static int gpmc_probe_dt(struct platform_device *pdev)
|
||||
else if (of_node_cmp(child->name, "onenand") == 0)
|
||||
ret = gpmc_probe_onenand_child(pdev, child);
|
||||
else if (of_node_cmp(child->name, "ethernet") == 0 ||
|
||||
of_node_cmp(child->name, "nor") == 0)
|
||||
of_node_cmp(child->name, "nor") == 0 ||
|
||||
of_node_cmp(child->name, "uart") == 0)
|
||||
ret = gpmc_probe_generic_child(pdev, child);
|
||||
else if (of_node_cmp(child->name, "8250") == 0)
|
||||
ret = gpmc_probe_8250(pdev, child);
|
||||
|
||||
if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
|
||||
__func__, child->full_name))
|
||||
|
@ -76,6 +76,13 @@ static inline void omap_barrier_reserve_memblock(void)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
|
||||
void set_cntfreq(void);
|
||||
#else
|
||||
static inline void set_cntfreq(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* OMAP_ARCH_OMAP_SECURE_H */
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "iomap.h"
|
||||
#include "common.h"
|
||||
#include "mmc.h"
|
||||
#include "hsmmc.h"
|
||||
#include "prminst44xx.h"
|
||||
#include "prcm_mpu44xx.h"
|
||||
#include "omap4-sar-layout.h"
|
||||
@ -284,59 +283,3 @@ skip_errata_init:
|
||||
omap_wakeupgen_init();
|
||||
irqchip_init();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
|
||||
static int omap4_twl6030_hsmmc_late_init(struct device *dev)
|
||||
{
|
||||
int irq = 0;
|
||||
struct platform_device *pdev = container_of(dev,
|
||||
struct platform_device, dev);
|
||||
struct omap_mmc_platform_data *pdata = dev->platform_data;
|
||||
|
||||
/* Setting MMC1 Card detect Irq */
|
||||
if (pdev->id == 0) {
|
||||
irq = twl6030_mmc_card_detect_config();
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "%s: Error card detect config(%d)\n",
|
||||
__func__, irq);
|
||||
return irq;
|
||||
}
|
||||
pdata->slots[0].card_detect_irq = irq;
|
||||
pdata->slots[0].card_detect = twl6030_mmc_card_detect;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
|
||||
{
|
||||
struct omap_mmc_platform_data *pdata;
|
||||
|
||||
/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
|
||||
if (!dev) {
|
||||
pr_err("Failed %s\n", __func__);
|
||||
return;
|
||||
}
|
||||
pdata = dev->platform_data;
|
||||
pdata->init = omap4_twl6030_hsmmc_late_init;
|
||||
}
|
||||
|
||||
int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
|
||||
{
|
||||
struct omap2_hsmmc_info *c;
|
||||
|
||||
omap_hsmmc_init(controllers);
|
||||
for (c = controllers; c->mmc; c++) {
|
||||
/* pdev can be null if CONFIG_MMC_OMAP_HS is not set */
|
||||
if (!c->pdev)
|
||||
continue;
|
||||
omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -120,7 +120,7 @@ static void omap3_save_secure_ram_context(void)
|
||||
* will hang the system.
|
||||
*/
|
||||
pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
|
||||
ret = _omap_save_secure_sram((u32 *)
|
||||
ret = _omap_save_secure_sram((u32 *)(unsigned long)
|
||||
__pa(omap3_secure_ram_storage));
|
||||
pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
|
||||
/* Following is for error tracking, it should not happen */
|
||||
|
@ -43,7 +43,7 @@ extern void omap4_prm_vcvp_write(u32 val, u8 offset);
|
||||
extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
|
||||
defined(CONFIG_SOC_DRA7XX)
|
||||
defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM43XX)
|
||||
void omap44xx_prm_reconfigure_io_chain(void);
|
||||
#else
|
||||
static inline void omap44xx_prm_reconfigure_io_chain(void)
|
||||
|
@ -209,13 +209,3 @@ void __init tegra_init_fuse(void)
|
||||
tegra_sku_id, tegra_cpu_process_id,
|
||||
tegra_core_process_id);
|
||||
}
|
||||
|
||||
unsigned long long tegra_chip_uid(void)
|
||||
{
|
||||
unsigned long long lo, hi;
|
||||
|
||||
lo = tegra_fuse_readl(FUSE_UID_LOW);
|
||||
hi = tegra_fuse_readl(FUSE_UID_HIGH);
|
||||
return (hi << 32ull) | lo;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_chip_uid);
|
||||
|
@ -53,6 +53,11 @@
|
||||
#define A15_BX_ADDR0 0x68
|
||||
#define A7_BX_ADDR0 0x78
|
||||
|
||||
/* SPC CPU/cluster reset statue */
|
||||
#define STANDBYWFI_STAT 0x3c
|
||||
#define STANDBYWFI_STAT_A15_CPU_MASK(cpu) (1 << (cpu))
|
||||
#define STANDBYWFI_STAT_A7_CPU_MASK(cpu) (1 << (3 + (cpu)))
|
||||
|
||||
/* SPC system config interface registers */
|
||||
#define SYSCFG_WDATA 0x70
|
||||
#define SYSCFG_RDATA 0x74
|
||||
@ -213,6 +218,41 @@ void ve_spc_powerdown(u32 cluster, bool enable)
|
||||
writel_relaxed(enable, info->baseaddr + pwdrn_reg);
|
||||
}
|
||||
|
||||
static u32 standbywfi_cpu_mask(u32 cpu, u32 cluster)
|
||||
{
|
||||
return cluster_is_a15(cluster) ?
|
||||
STANDBYWFI_STAT_A15_CPU_MASK(cpu)
|
||||
: STANDBYWFI_STAT_A7_CPU_MASK(cpu);
|
||||
}
|
||||
|
||||
/**
|
||||
* ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
|
||||
*
|
||||
* @cpu: mpidr[7:0] bitfield describing CPU affinity level within cluster
|
||||
* @cluster: mpidr[15:8] bitfield describing cluster affinity level
|
||||
*
|
||||
* @return: non-zero if and only if the specified CPU is in WFI
|
||||
*
|
||||
* Take care when interpreting the result of this function: a CPU might
|
||||
* be in WFI temporarily due to idle, and is not necessarily safely
|
||||
* parked.
|
||||
*/
|
||||
int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
|
||||
{
|
||||
int ret;
|
||||
u32 mask = standbywfi_cpu_mask(cpu, cluster);
|
||||
|
||||
if (cluster >= MAX_CLUSTERS)
|
||||
return 1;
|
||||
|
||||
ret = readl_relaxed(info->baseaddr + STANDBYWFI_STAT);
|
||||
|
||||
pr_debug("%s: PCFGREG[0x%X] = 0x%08X, mask = 0x%X\n",
|
||||
__func__, STANDBYWFI_STAT, ret, mask);
|
||||
|
||||
return ret & mask;
|
||||
}
|
||||
|
||||
static int ve_spc_get_performance(int cluster, u32 *freq)
|
||||
{
|
||||
struct ve_spc_opp *opps = info->opps[cluster];
|
||||
|
@ -20,5 +20,6 @@ void ve_spc_global_wakeup_irq(bool set);
|
||||
void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set);
|
||||
void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr);
|
||||
void ve_spc_powerdown(u32 cluster, bool enable);
|
||||
int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster);
|
||||
|
||||
#endif
|
||||
|
@ -12,6 +12,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -32,11 +33,17 @@
|
||||
#include "spc.h"
|
||||
|
||||
/* SCC conf registers */
|
||||
#define RESET_CTRL 0x018
|
||||
#define RESET_A15_NCORERESET(cpu) (1 << (2 + (cpu)))
|
||||
#define RESET_A7_NCORERESET(cpu) (1 << (16 + (cpu)))
|
||||
|
||||
#define A15_CONF 0x400
|
||||
#define A7_CONF 0x500
|
||||
#define SYS_INFO 0x700
|
||||
#define SPC_BASE 0xb00
|
||||
|
||||
static void __iomem *scc;
|
||||
|
||||
/*
|
||||
* We can't use regular spinlocks. In the switcher case, it is possible
|
||||
* for an outbound CPU to call power_down() after its inbound counterpart
|
||||
@ -190,6 +197,55 @@ static void tc2_pm_power_down(void)
|
||||
tc2_pm_down(0);
|
||||
}
|
||||
|
||||
static int tc2_core_in_reset(unsigned int cpu, unsigned int cluster)
|
||||
{
|
||||
u32 mask = cluster ?
|
||||
RESET_A7_NCORERESET(cpu)
|
||||
: RESET_A15_NCORERESET(cpu);
|
||||
|
||||
return !(readl_relaxed(scc + RESET_CTRL) & mask);
|
||||
}
|
||||
|
||||
#define POLL_MSEC 10
|
||||
#define TIMEOUT_MSEC 1000
|
||||
|
||||
static int tc2_pm_power_down_finish(unsigned int cpu, unsigned int cluster)
|
||||
{
|
||||
unsigned tries;
|
||||
|
||||
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
|
||||
BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
|
||||
|
||||
for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; ++tries) {
|
||||
/*
|
||||
* Only examine the hardware state if the target CPU has
|
||||
* caught up at least as far as tc2_pm_down():
|
||||
*/
|
||||
if (ACCESS_ONCE(tc2_pm_use_count[cpu][cluster]) == 0) {
|
||||
pr_debug("%s(cpu=%u, cluster=%u): RESET_CTRL = 0x%08X\n",
|
||||
__func__, cpu, cluster,
|
||||
readl_relaxed(scc + RESET_CTRL));
|
||||
|
||||
/*
|
||||
* We need the CPU to reach WFI, but the power
|
||||
* controller may put the cluster in reset and
|
||||
* power it off as soon as that happens, before
|
||||
* we have a chance to see STANDBYWFI.
|
||||
*
|
||||
* So we need to check for both conditions:
|
||||
*/
|
||||
if (tc2_core_in_reset(cpu, cluster) ||
|
||||
ve_spc_cpu_in_wfi(cpu, cluster))
|
||||
return 0; /* success: the CPU is halted */
|
||||
}
|
||||
|
||||
/* Otherwise, wait and retry: */
|
||||
msleep(POLL_MSEC);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT; /* timeout */
|
||||
}
|
||||
|
||||
static void tc2_pm_suspend(u64 residency)
|
||||
{
|
||||
unsigned int mpidr, cpu, cluster;
|
||||
@ -232,10 +288,11 @@ static void tc2_pm_powered_up(void)
|
||||
}
|
||||
|
||||
static const struct mcpm_platform_ops tc2_pm_power_ops = {
|
||||
.power_up = tc2_pm_power_up,
|
||||
.power_down = tc2_pm_power_down,
|
||||
.suspend = tc2_pm_suspend,
|
||||
.powered_up = tc2_pm_powered_up,
|
||||
.power_up = tc2_pm_power_up,
|
||||
.power_down = tc2_pm_power_down,
|
||||
.power_down_finish = tc2_pm_power_down_finish,
|
||||
.suspend = tc2_pm_suspend,
|
||||
.powered_up = tc2_pm_powered_up,
|
||||
};
|
||||
|
||||
static bool __init tc2_pm_usage_count_init(void)
|
||||
@ -269,7 +326,6 @@ static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
|
||||
static int __init tc2_pm_init(void)
|
||||
{
|
||||
int ret, irq;
|
||||
void __iomem *scc;
|
||||
u32 a15_cluster_id, a7_cluster_id, sys_info;
|
||||
struct device_node *np;
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/memreserve/ 0x80000000 0x00010000;
|
||||
|
||||
/ {
|
||||
model = "Foundation-v8A";
|
||||
compatible = "arm,foundation-aarch64", "arm,vexpress";
|
||||
|
@ -56,6 +56,9 @@ static inline void arch_local_irq_disable(void)
|
||||
#define local_fiq_enable() asm("msr daifclr, #1" : : : "memory")
|
||||
#define local_fiq_disable() asm("msr daifset, #1" : : : "memory")
|
||||
|
||||
#define local_async_enable() asm("msr daifclr, #4" : : : "memory")
|
||||
#define local_async_disable() asm("msr daifset, #4" : : : "memory")
|
||||
|
||||
/*
|
||||
* Save the current interrupt enable state.
|
||||
*/
|
||||
|
@ -25,10 +25,11 @@
|
||||
* Software defined PTE bits definition.
|
||||
*/
|
||||
#define PTE_VALID (_AT(pteval_t, 1) << 0)
|
||||
#define PTE_PROT_NONE (_AT(pteval_t, 1) << 2) /* only when !PTE_VALID */
|
||||
#define PTE_FILE (_AT(pteval_t, 1) << 3) /* only when !pte_present() */
|
||||
#define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */
|
||||
#define PTE_DIRTY (_AT(pteval_t, 1) << 55)
|
||||
#define PTE_SPECIAL (_AT(pteval_t, 1) << 56)
|
||||
/* bit 57 for PMD_SECT_SPLITTING */
|
||||
#define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
|
||||
|
||||
/*
|
||||
* VMALLOC and SPARSEMEM_VMEMMAP ranges.
|
||||
@ -254,7 +255,7 @@ static inline int has_transparent_hugepage(void)
|
||||
#define pgprot_noncached(prot) \
|
||||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE))
|
||||
#define pgprot_writecombine(prot) \
|
||||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE))
|
||||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
|
||||
#define pgprot_dmacoherent(prot) \
|
||||
__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
|
||||
#define __HAVE_PHYS_MEM_ACCESS_PROT
|
||||
@ -357,18 +358,20 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
|
||||
|
||||
/*
|
||||
* Encode and decode a swap entry:
|
||||
* bits 0, 2: present (must both be zero)
|
||||
* bit 3: PTE_FILE
|
||||
* bits 4-8: swap type
|
||||
* bits 9-63: swap offset
|
||||
* bits 0-1: present (must be zero)
|
||||
* bit 2: PTE_FILE
|
||||
* bits 3-8: swap type
|
||||
* bits 9-57: swap offset
|
||||
*/
|
||||
#define __SWP_TYPE_SHIFT 4
|
||||
#define __SWP_TYPE_SHIFT 3
|
||||
#define __SWP_TYPE_BITS 6
|
||||
#define __SWP_OFFSET_BITS 49
|
||||
#define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1)
|
||||
#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
|
||||
#define __SWP_OFFSET_MASK ((1UL << __SWP_OFFSET_BITS) - 1)
|
||||
|
||||
#define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
|
||||
#define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT)
|
||||
#define __swp_offset(x) (((x).val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK)
|
||||
#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
|
||||
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
@ -382,15 +385,15 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
|
||||
|
||||
/*
|
||||
* Encode and decode a file entry:
|
||||
* bits 0, 2: present (must both be zero)
|
||||
* bit 3: PTE_FILE
|
||||
* bits 4-63: file offset / PAGE_SIZE
|
||||
* bits 0-1: present (must be zero)
|
||||
* bit 2: PTE_FILE
|
||||
* bits 3-57: file offset / PAGE_SIZE
|
||||
*/
|
||||
#define pte_file(pte) (pte_val(pte) & PTE_FILE)
|
||||
#define pte_to_pgoff(x) (pte_val(x) >> 4)
|
||||
#define pgoff_to_pte(x) __pte(((x) << 4) | PTE_FILE)
|
||||
#define pte_to_pgoff(x) (pte_val(x) >> 3)
|
||||
#define pgoff_to_pte(x) __pte(((x) << 3) | PTE_FILE)
|
||||
|
||||
#define PTE_FILE_MAX_BITS 60
|
||||
#define PTE_FILE_MAX_BITS 55
|
||||
|
||||
extern int kern_addr_valid(unsigned long addr);
|
||||
|
||||
|
@ -248,7 +248,8 @@ static int brk_handler(unsigned long addr, unsigned int esr,
|
||||
int aarch32_break_handler(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
unsigned int instr;
|
||||
u32 arm_instr;
|
||||
u16 thumb_instr;
|
||||
bool bp = false;
|
||||
void __user *pc = (void __user *)instruction_pointer(regs);
|
||||
|
||||
@ -257,18 +258,21 @@ int aarch32_break_handler(struct pt_regs *regs)
|
||||
|
||||
if (compat_thumb_mode(regs)) {
|
||||
/* get 16-bit Thumb instruction */
|
||||
get_user(instr, (u16 __user *)pc);
|
||||
if (instr == AARCH32_BREAK_THUMB2_LO) {
|
||||
get_user(thumb_instr, (u16 __user *)pc);
|
||||
thumb_instr = le16_to_cpu(thumb_instr);
|
||||
if (thumb_instr == AARCH32_BREAK_THUMB2_LO) {
|
||||
/* get second half of 32-bit Thumb-2 instruction */
|
||||
get_user(instr, (u16 __user *)(pc + 2));
|
||||
bp = instr == AARCH32_BREAK_THUMB2_HI;
|
||||
get_user(thumb_instr, (u16 __user *)(pc + 2));
|
||||
thumb_instr = le16_to_cpu(thumb_instr);
|
||||
bp = thumb_instr == AARCH32_BREAK_THUMB2_HI;
|
||||
} else {
|
||||
bp = instr == AARCH32_BREAK_THUMB;
|
||||
bp = thumb_instr == AARCH32_BREAK_THUMB;
|
||||
}
|
||||
} else {
|
||||
/* 32-bit ARM instruction */
|
||||
get_user(instr, (u32 __user *)pc);
|
||||
bp = (instr & ~0xf0000000) == AARCH32_BREAK_ARM;
|
||||
get_user(arm_instr, (u32 __user *)pc);
|
||||
arm_instr = le32_to_cpu(arm_instr);
|
||||
bp = (arm_instr & ~0xf0000000) == AARCH32_BREAK_ARM;
|
||||
}
|
||||
|
||||
if (!bp)
|
||||
|
@ -309,15 +309,12 @@ el1_irq:
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
bl trace_hardirqs_off
|
||||
#endif
|
||||
|
||||
irq_handler
|
||||
|
||||
#ifdef CONFIG_PREEMPT
|
||||
get_thread_info tsk
|
||||
ldr w24, [tsk, #TI_PREEMPT] // get preempt count
|
||||
add w0, w24, #1 // increment it
|
||||
str w0, [tsk, #TI_PREEMPT]
|
||||
#endif
|
||||
irq_handler
|
||||
#ifdef CONFIG_PREEMPT
|
||||
str w24, [tsk, #TI_PREEMPT] // restore preempt count
|
||||
ldr w24, [tsk, #TI_PREEMPT] // restore preempt count
|
||||
cbnz w24, 1f // preempt count != 0
|
||||
ldr x0, [tsk, #TI_FLAGS] // get flags
|
||||
tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
|
||||
@ -507,22 +504,10 @@ el0_irq_naked:
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
bl trace_hardirqs_off
|
||||
#endif
|
||||
get_thread_info tsk
|
||||
#ifdef CONFIG_PREEMPT
|
||||
ldr w24, [tsk, #TI_PREEMPT] // get preempt count
|
||||
add w23, w24, #1 // increment it
|
||||
str w23, [tsk, #TI_PREEMPT]
|
||||
#endif
|
||||
|
||||
irq_handler
|
||||
#ifdef CONFIG_PREEMPT
|
||||
ldr w0, [tsk, #TI_PREEMPT]
|
||||
str w24, [tsk, #TI_PREEMPT]
|
||||
cmp w0, w23
|
||||
b.eq 1f
|
||||
mov x1, #0
|
||||
str x1, [x1] // BUG
|
||||
1:
|
||||
#endif
|
||||
get_thread_info tsk
|
||||
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
bl trace_hardirqs_on
|
||||
#endif
|
||||
|
@ -636,28 +636,27 @@ static int compat_gpr_get(struct task_struct *target,
|
||||
|
||||
for (i = 0; i < num_regs; ++i) {
|
||||
unsigned int idx = start + i;
|
||||
void *reg;
|
||||
compat_ulong_t reg;
|
||||
|
||||
switch (idx) {
|
||||
case 15:
|
||||
reg = (void *)&task_pt_regs(target)->pc;
|
||||
reg = task_pt_regs(target)->pc;
|
||||
break;
|
||||
case 16:
|
||||
reg = (void *)&task_pt_regs(target)->pstate;
|
||||
reg = task_pt_regs(target)->pstate;
|
||||
break;
|
||||
case 17:
|
||||
reg = (void *)&task_pt_regs(target)->orig_x0;
|
||||
reg = task_pt_regs(target)->orig_x0;
|
||||
break;
|
||||
default:
|
||||
reg = (void *)&task_pt_regs(target)->regs[idx];
|
||||
reg = task_pt_regs(target)->regs[idx];
|
||||
}
|
||||
|
||||
ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t));
|
||||
|
||||
ret = copy_to_user(ubuf, ®, sizeof(reg));
|
||||
if (ret)
|
||||
break;
|
||||
else
|
||||
ubuf += sizeof(compat_ulong_t);
|
||||
|
||||
ubuf += sizeof(reg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -685,28 +684,28 @@ static int compat_gpr_set(struct task_struct *target,
|
||||
|
||||
for (i = 0; i < num_regs; ++i) {
|
||||
unsigned int idx = start + i;
|
||||
void *reg;
|
||||
compat_ulong_t reg;
|
||||
|
||||
ret = copy_from_user(®, ubuf, sizeof(reg));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ubuf += sizeof(reg);
|
||||
|
||||
switch (idx) {
|
||||
case 15:
|
||||
reg = (void *)&newregs.pc;
|
||||
newregs.pc = reg;
|
||||
break;
|
||||
case 16:
|
||||
reg = (void *)&newregs.pstate;
|
||||
newregs.pstate = reg;
|
||||
break;
|
||||
case 17:
|
||||
reg = (void *)&newregs.orig_x0;
|
||||
newregs.orig_x0 = reg;
|
||||
break;
|
||||
default:
|
||||
reg = (void *)&newregs.regs[idx];
|
||||
newregs.regs[idx] = reg;
|
||||
}
|
||||
|
||||
ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t));
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
else
|
||||
ubuf += sizeof(compat_ulong_t);
|
||||
}
|
||||
|
||||
if (valid_user_regs(&newregs.user_regs))
|
||||
@ -714,7 +713,6 @@ static int compat_gpr_set(struct task_struct *target,
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -205,6 +205,11 @@ u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
/*
|
||||
* Unmask asynchronous aborts early to catch possible system errors.
|
||||
*/
|
||||
local_async_enable();
|
||||
|
||||
setup_processor();
|
||||
|
||||
setup_machine_fdt(__fdt_pointer);
|
||||
|
@ -160,6 +160,7 @@ asmlinkage void secondary_start_kernel(void)
|
||||
|
||||
local_irq_enable();
|
||||
local_fiq_enable();
|
||||
local_async_enable();
|
||||
|
||||
/*
|
||||
* OK, it's off to the idle thread for us
|
||||
|
@ -75,8 +75,10 @@ LDEMULATION := lppc
|
||||
GNUTARGET := powerpcle
|
||||
MULTIPLEWORD := -mno-multiple
|
||||
else
|
||||
ifeq ($(call cc-option-yn,-mbig-endian),y)
|
||||
override CC += -mbig-endian
|
||||
override AS += -mbig-endian
|
||||
endif
|
||||
override LD += -EB
|
||||
LDEMULATION := ppc
|
||||
GNUTARGET := powerpc
|
||||
@ -128,7 +130,12 @@ CFLAGS-$(CONFIG_POWER5_CPU) += $(call cc-option,-mcpu=power5)
|
||||
CFLAGS-$(CONFIG_POWER6_CPU) += $(call cc-option,-mcpu=power6)
|
||||
CFLAGS-$(CONFIG_POWER7_CPU) += $(call cc-option,-mcpu=power7)
|
||||
|
||||
# Altivec option not allowed with e500mc64 in GCC.
|
||||
ifeq ($(CONFIG_ALTIVEC),y)
|
||||
E5500_CPU := -mcpu=powerpc64
|
||||
else
|
||||
E5500_CPU := $(call cc-option,-mcpu=e500mc64,-mcpu=powerpc64)
|
||||
endif
|
||||
CFLAGS-$(CONFIG_E5500_CPU) += $(E5500_CPU)
|
||||
CFLAGS-$(CONFIG_E6500_CPU) += $(call cc-option,-mcpu=e6500,$(E5500_CPU))
|
||||
|
||||
|
@ -637,14 +637,14 @@
|
||||
tlu@2f000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x2f000 0x1000>;
|
||||
interupts = <61 2 >;
|
||||
interrupts = <61 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
tlu@15000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x15000 0x1000>;
|
||||
interupts = <75 2>;
|
||||
interrupts = <75 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
@ -547,14 +547,14 @@
|
||||
tlu@2f000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x2f000 0x1000>;
|
||||
interupts = <61 2 >;
|
||||
interrupts = <61 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
tlu@15000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x15000 0x1000>;
|
||||
interupts = <75 2>;
|
||||
interrupts = <75 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
@ -583,14 +583,14 @@
|
||||
tlu@2f000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x2f000 0x1000>;
|
||||
interupts = <61 2 >;
|
||||
interrupts = <61 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
tlu@15000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x15000 0x1000>;
|
||||
interupts = <75 2>;
|
||||
interrupts = <75 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
@ -545,14 +545,14 @@
|
||||
tlu@2f000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x2f000 0x1000>;
|
||||
interupts = <61 2 >;
|
||||
interrupts = <61 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
tlu@15000 {
|
||||
compatible = "fsl,mpc8572-tlu", "fsl_tlu";
|
||||
reg = <0x15000 0x1000>;
|
||||
interupts = <75 2>;
|
||||
interrupts = <75 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
};
|
||||
|
@ -71,18 +71,32 @@ udelay:
|
||||
add r4,r4,r5
|
||||
addi r4,r4,-1
|
||||
divw r4,r4,r5 /* BUS ticks */
|
||||
#ifdef CONFIG_8xx
|
||||
1: mftbu r5
|
||||
mftb r6
|
||||
mftbu r7
|
||||
#else
|
||||
1: mfspr r5, SPRN_TBRU
|
||||
mfspr r6, SPRN_TBRL
|
||||
mfspr r7, SPRN_TBRU
|
||||
#endif
|
||||
cmpw 0,r5,r7
|
||||
bne 1b /* Get [synced] base time */
|
||||
addc r9,r6,r4 /* Compute end time */
|
||||
addze r8,r5
|
||||
#ifdef CONFIG_8xx
|
||||
2: mftbu r5
|
||||
#else
|
||||
2: mfspr r5, SPRN_TBRU
|
||||
#endif
|
||||
cmpw 0,r5,r8
|
||||
blt 2b
|
||||
bgt 3f
|
||||
#ifdef CONFIG_8xx
|
||||
mftb r6
|
||||
#else
|
||||
mfspr r6, SPRN_TBRL
|
||||
#endif
|
||||
cmpw 0,r6,r9
|
||||
blt 2b
|
||||
3: blr
|
||||
|
@ -16,6 +16,7 @@ struct vmemmap_backing {
|
||||
unsigned long phys;
|
||||
unsigned long virt_addr;
|
||||
};
|
||||
extern struct vmemmap_backing *vmemmap_list;
|
||||
|
||||
/*
|
||||
* Functions that deal with pagetables that could be at any level of
|
||||
|
@ -366,6 +366,8 @@ BEGIN_FTR_SECTION_NESTED(96); \
|
||||
cmpwi dest,0; \
|
||||
beq- 90b; \
|
||||
END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
|
||||
#elif defined(CONFIG_8xx)
|
||||
#define MFTB(dest) mftb dest
|
||||
#else
|
||||
#define MFTB(dest) mfspr dest, SPRN_TBRL
|
||||
#endif
|
||||
|
@ -1174,12 +1174,19 @@
|
||||
|
||||
#else /* __powerpc64__ */
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
#define mftbl() ({unsigned long rval; \
|
||||
asm volatile("mftbl %0" : "=r" (rval)); rval;})
|
||||
#define mftbu() ({unsigned long rval; \
|
||||
asm volatile("mftbu %0" : "=r" (rval)); rval;})
|
||||
#else
|
||||
#define mftbl() ({unsigned long rval; \
|
||||
asm volatile("mfspr %0, %1" : "=r" (rval) : \
|
||||
"i" (SPRN_TBRL)); rval;})
|
||||
#define mftbu() ({unsigned long rval; \
|
||||
asm volatile("mfspr %0, %1" : "=r" (rval) : \
|
||||
"i" (SPRN_TBRU)); rval;})
|
||||
#endif
|
||||
#endif /* !__powerpc64__ */
|
||||
|
||||
#define mttbl(v) asm volatile("mttbl %0":: "r"(v))
|
||||
|
@ -29,7 +29,11 @@ static inline cycles_t get_cycles(void)
|
||||
ret = 0;
|
||||
|
||||
__asm__ __volatile__(
|
||||
#ifdef CONFIG_8xx
|
||||
"97: mftb %0\n"
|
||||
#else
|
||||
"97: mfspr %0, %2\n"
|
||||
#endif
|
||||
"99:\n"
|
||||
".section __ftr_fixup,\"a\"\n"
|
||||
".align 2\n"
|
||||
@ -41,7 +45,11 @@ static inline cycles_t get_cycles(void)
|
||||
" .long 0\n"
|
||||
" .long 0\n"
|
||||
".previous"
|
||||
#ifdef CONFIG_8xx
|
||||
: "=r" (ret) : "i" (CPU_FTR_601));
|
||||
#else
|
||||
: "=r" (ret) : "i" (CPU_FTR_601), "i" (SPRN_TBRL));
|
||||
#endif
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
@ -75,6 +76,17 @@ void arch_crash_save_vmcoreinfo(void)
|
||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||
VMCOREINFO_SYMBOL(contig_page_data);
|
||||
#endif
|
||||
#if defined(CONFIG_PPC64) && defined(CONFIG_SPARSEMEM_VMEMMAP)
|
||||
VMCOREINFO_SYMBOL(vmemmap_list);
|
||||
VMCOREINFO_SYMBOL(mmu_vmemmap_psize);
|
||||
VMCOREINFO_SYMBOL(mmu_psize_defs);
|
||||
VMCOREINFO_STRUCT_SIZE(vmemmap_backing);
|
||||
VMCOREINFO_OFFSET(vmemmap_backing, list);
|
||||
VMCOREINFO_OFFSET(vmemmap_backing, phys);
|
||||
VMCOREINFO_OFFSET(vmemmap_backing, virt_addr);
|
||||
VMCOREINFO_STRUCT_SIZE(mmu_psize_def);
|
||||
VMCOREINFO_OFFSET(mmu_psize_def, shift);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -210,7 +210,7 @@ static void __init nvram_print_partitions(char * label)
|
||||
printk(KERN_WARNING "--------%s---------\n", label);
|
||||
printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
|
||||
list_for_each_entry(tmp_part, &nvram_partitions, partition) {
|
||||
printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12s\n",
|
||||
printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12.12s\n",
|
||||
tmp_part->index, tmp_part->header.signature,
|
||||
tmp_part->header.checksum, tmp_part->header.length,
|
||||
tmp_part->header.name);
|
||||
|
@ -445,6 +445,12 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
if (copy_fpr_to_user(&frame->mc_fregs, current))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Clear the MSR VSX bit to indicate there is no valid state attached
|
||||
* to this context, except in the specific case below where we set it.
|
||||
*/
|
||||
msr &= ~MSR_VSX;
|
||||
#ifdef CONFIG_VSX
|
||||
/*
|
||||
* Copy VSR 0-31 upper half from thread_struct to local
|
||||
@ -457,15 +463,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
|
||||
if (copy_vsx_to_user(&frame->mc_vsregs, current))
|
||||
return 1;
|
||||
msr |= MSR_VSX;
|
||||
} else if (!ctx_has_vsx_region)
|
||||
/*
|
||||
* With a small context structure we can't hold the VSX
|
||||
* registers, hence clear the MSR value to indicate the state
|
||||
* was not saved.
|
||||
*/
|
||||
msr &= ~MSR_VSX;
|
||||
|
||||
|
||||
}
|
||||
#endif /* CONFIG_VSX */
|
||||
#ifdef CONFIG_SPE
|
||||
/* save spe registers */
|
||||
|
@ -122,6 +122,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
flush_fp_to_thread(current);
|
||||
/* copy fpr regs and fpscr */
|
||||
err |= copy_fpr_to_user(&sc->fp_regs, current);
|
||||
|
||||
/*
|
||||
* Clear the MSR VSX bit to indicate there is no valid state attached
|
||||
* to this context, except in the specific case below where we set it.
|
||||
*/
|
||||
msr &= ~MSR_VSX;
|
||||
#ifdef CONFIG_VSX
|
||||
/*
|
||||
* Copy VSX low doubleword to local buffer for formatting,
|
||||
|
@ -232,9 +232,15 @@ __do_get_tspec:
|
||||
lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
|
||||
|
||||
/* Get a stable TB value */
|
||||
#ifdef CONFIG_8xx
|
||||
2: mftbu r3
|
||||
mftbl r4
|
||||
mftbu r0
|
||||
#else
|
||||
2: mfspr r3, SPRN_TBRU
|
||||
mfspr r4, SPRN_TBRL
|
||||
mfspr r0, SPRN_TBRU
|
||||
#endif
|
||||
cmplw cr0,r3,r0
|
||||
bne- 2b
|
||||
|
||||
|
@ -117,6 +117,5 @@ void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
|
||||
struct hstate *hstate = hstate_file(vma->vm_file);
|
||||
unsigned long tsize = huge_page_shift(hstate) - 10;
|
||||
|
||||
__flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, tsize, 0);
|
||||
|
||||
__flush_tlb_page(vma->vm_mm, vmaddr, tsize, 0);
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
|
||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
|
||||
{
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
if (is_vm_hugetlb_page(vma))
|
||||
if (vma && is_vm_hugetlb_page(vma))
|
||||
flush_hugetlb_page(vma, vmaddr);
|
||||
#endif
|
||||
|
||||
|
@ -404,13 +404,27 @@ config PPC_DOORBELL
|
||||
|
||||
endmenu
|
||||
|
||||
config CPU_LITTLE_ENDIAN
|
||||
bool "Build little endian kernel"
|
||||
default n
|
||||
choice
|
||||
prompt "Endianness selection"
|
||||
default CPU_BIG_ENDIAN
|
||||
help
|
||||
This option selects whether a big endian or little endian kernel will
|
||||
be built.
|
||||
|
||||
config CPU_BIG_ENDIAN
|
||||
bool "Build big endian kernel"
|
||||
help
|
||||
Build a big endian kernel.
|
||||
|
||||
If unsure, select this option.
|
||||
|
||||
config CPU_LITTLE_ENDIAN
|
||||
bool "Build little endian kernel"
|
||||
help
|
||||
Build a little endian kernel.
|
||||
|
||||
Note that if cross compiling a little endian kernel,
|
||||
CROSS_COMPILE must point to a toolchain capable of targeting
|
||||
little endian powerpc.
|
||||
|
||||
endchoice
|
||||
|
@ -101,7 +101,7 @@ config S390
|
||||
select GENERIC_CPU_DEVICES if !SMP
|
||||
select GENERIC_FIND_FIRST_BIT
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL_OLD
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
|
||||
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
|
@ -35,7 +35,6 @@ static u8 *ctrblk;
|
||||
static char keylen_flag;
|
||||
|
||||
struct s390_aes_ctx {
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
u8 key[AES_MAX_KEY_SIZE];
|
||||
long enc;
|
||||
long dec;
|
||||
@ -441,30 +440,36 @@ static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
return aes_set_key(tfm, in_key, key_len);
|
||||
}
|
||||
|
||||
static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
|
||||
static int cbc_aes_crypt(struct blkcipher_desc *desc, long func,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
int ret = blkcipher_walk_virt(desc, walk);
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
struct {
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
u8 key[AES_MAX_KEY_SIZE];
|
||||
} param;
|
||||
|
||||
if (!nbytes)
|
||||
goto out;
|
||||
|
||||
memcpy(param, walk->iv, AES_BLOCK_SIZE);
|
||||
memcpy(param.iv, walk->iv, AES_BLOCK_SIZE);
|
||||
memcpy(param.key, sctx->key, sctx->key_len);
|
||||
do {
|
||||
/* only use complete blocks */
|
||||
unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
|
||||
u8 *out = walk->dst.virt.addr;
|
||||
u8 *in = walk->src.virt.addr;
|
||||
|
||||
ret = crypt_s390_kmc(func, param, out, in, n);
|
||||
ret = crypt_s390_kmc(func, ¶m, out, in, n);
|
||||
if (ret < 0 || ret != n)
|
||||
return -EIO;
|
||||
|
||||
nbytes &= AES_BLOCK_SIZE - 1;
|
||||
ret = blkcipher_walk_done(desc, walk, nbytes);
|
||||
} while ((nbytes = walk->nbytes));
|
||||
memcpy(walk->iv, param, AES_BLOCK_SIZE);
|
||||
memcpy(walk->iv, param.iv, AES_BLOCK_SIZE);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@ -481,7 +486,7 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
|
||||
return fallback_blk_enc(desc, dst, src, nbytes);
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
|
||||
return cbc_aes_crypt(desc, sctx->enc, &walk);
|
||||
}
|
||||
|
||||
static int cbc_aes_decrypt(struct blkcipher_desc *desc,
|
||||
@ -495,7 +500,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
|
||||
return fallback_blk_dec(desc, dst, src, nbytes);
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
|
||||
return cbc_aes_crypt(desc, sctx->dec, &walk);
|
||||
}
|
||||
|
||||
static struct crypto_alg cbc_aes_alg = {
|
||||
|
@ -48,33 +48,21 @@ static inline void clear_page(void *page)
|
||||
: "memory", "cc");
|
||||
}
|
||||
|
||||
/*
|
||||
* copy_page uses the mvcl instruction with 0xb0 padding byte in order to
|
||||
* bypass caches when copying a page. Especially when copying huge pages
|
||||
* this keeps L1 and L2 data caches alive.
|
||||
*/
|
||||
static inline void copy_page(void *to, void *from)
|
||||
{
|
||||
if (MACHINE_HAS_MVPG) {
|
||||
register unsigned long reg0 asm ("0") = 0;
|
||||
asm volatile(
|
||||
" mvpg %0,%1"
|
||||
: : "a" (to), "a" (from), "d" (reg0)
|
||||
: "memory", "cc");
|
||||
} else
|
||||
asm volatile(
|
||||
" mvc 0(256,%0),0(%1)\n"
|
||||
" mvc 256(256,%0),256(%1)\n"
|
||||
" mvc 512(256,%0),512(%1)\n"
|
||||
" mvc 768(256,%0),768(%1)\n"
|
||||
" mvc 1024(256,%0),1024(%1)\n"
|
||||
" mvc 1280(256,%0),1280(%1)\n"
|
||||
" mvc 1536(256,%0),1536(%1)\n"
|
||||
" mvc 1792(256,%0),1792(%1)\n"
|
||||
" mvc 2048(256,%0),2048(%1)\n"
|
||||
" mvc 2304(256,%0),2304(%1)\n"
|
||||
" mvc 2560(256,%0),2560(%1)\n"
|
||||
" mvc 2816(256,%0),2816(%1)\n"
|
||||
" mvc 3072(256,%0),3072(%1)\n"
|
||||
" mvc 3328(256,%0),3328(%1)\n"
|
||||
" mvc 3584(256,%0),3584(%1)\n"
|
||||
" mvc 3840(256,%0),3840(%1)\n"
|
||||
: : "a" (to), "a" (from) : "memory");
|
||||
register void *reg2 asm ("2") = to;
|
||||
register unsigned long reg3 asm ("3") = 0x1000;
|
||||
register void *reg4 asm ("4") = from;
|
||||
register unsigned long reg5 asm ("5") = 0xb0001000;
|
||||
asm volatile(
|
||||
" mvcl 2,4"
|
||||
: "+d" (reg2), "+d" (reg3), "+d" (reg4), "+d" (reg5)
|
||||
: : "memory", "cc");
|
||||
}
|
||||
|
||||
#define clear_user_page(page, vaddr, pg) clear_page(page)
|
||||
|
@ -26,8 +26,9 @@ struct vdso_data {
|
||||
__u64 wtom_clock_nsec; /* 0x28 */
|
||||
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */
|
||||
__u32 tz_dsttime; /* Type of dst correction 0x34 */
|
||||
__u32 ectg_available;
|
||||
__u32 ntp_mult; /* NTP adjusted multiplier 0x3C */
|
||||
__u32 ectg_available; /* ECTG instruction present 0x38 */
|
||||
__u32 tk_mult; /* Mult. used for xtime_nsec 0x3c */
|
||||
__u32 tk_shift; /* Shift used for xtime_nsec 0x40 */
|
||||
};
|
||||
|
||||
struct vdso_per_cpu_data {
|
||||
|
@ -65,7 +65,8 @@ int main(void)
|
||||
DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
|
||||
DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
|
||||
DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
|
||||
DEFINE(__VDSO_NTP_MULT, offsetof(struct vdso_data, ntp_mult));
|
||||
DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult));
|
||||
DEFINE(__VDSO_TK_SHIFT, offsetof(struct vdso_data, tk_shift));
|
||||
DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base));
|
||||
DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time));
|
||||
/* constants used by the vdso */
|
||||
|
@ -194,7 +194,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
|
||||
return -EINVAL;
|
||||
|
||||
/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
|
||||
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
|
||||
regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
|
||||
(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 |
|
||||
(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 |
|
||||
(__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE);
|
||||
|
@ -78,7 +78,7 @@ PGM_CHECK_DEFAULT /* 34 */
|
||||
PGM_CHECK_DEFAULT /* 35 */
|
||||
PGM_CHECK_DEFAULT /* 36 */
|
||||
PGM_CHECK_DEFAULT /* 37 */
|
||||
PGM_CHECK_DEFAULT /* 38 */
|
||||
PGM_CHECK_64BIT(do_dat_exception) /* 38 */
|
||||
PGM_CHECK_64BIT(do_dat_exception) /* 39 */
|
||||
PGM_CHECK_64BIT(do_dat_exception) /* 3a */
|
||||
PGM_CHECK_64BIT(do_dat_exception) /* 3b */
|
||||
|
@ -94,7 +94,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
|
||||
return -EINVAL;
|
||||
|
||||
/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
|
||||
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
|
||||
regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
|
||||
(user_sregs.regs.psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
|
||||
/* Check for invalid user address space control. */
|
||||
if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
|
||||
|
@ -108,20 +108,10 @@ static void fixup_clock_comparator(unsigned long long delta)
|
||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||
}
|
||||
|
||||
static int s390_next_ktime(ktime_t expires,
|
||||
static int s390_next_event(unsigned long delta,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
struct timespec ts;
|
||||
u64 nsecs;
|
||||
|
||||
ts.tv_sec = ts.tv_nsec = 0;
|
||||
monotonic_to_bootbased(&ts);
|
||||
nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires));
|
||||
do_div(nsecs, 125);
|
||||
S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9);
|
||||
/* Program the maximum value if we have an overflow (== year 2042) */
|
||||
if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc))
|
||||
S390_lowcore.clock_comparator = -1ULL;
|
||||
S390_lowcore.clock_comparator = get_tod_clock() + delta;
|
||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||
return 0;
|
||||
}
|
||||
@ -146,15 +136,14 @@ void init_cpu_timer(void)
|
||||
cpu = smp_processor_id();
|
||||
cd = &per_cpu(comparators, cpu);
|
||||
cd->name = "comparator";
|
||||
cd->features = CLOCK_EVT_FEAT_ONESHOT |
|
||||
CLOCK_EVT_FEAT_KTIME;
|
||||
cd->features = CLOCK_EVT_FEAT_ONESHOT;
|
||||
cd->mult = 16777;
|
||||
cd->shift = 12;
|
||||
cd->min_delta_ns = 1;
|
||||
cd->max_delta_ns = LONG_MAX;
|
||||
cd->rating = 400;
|
||||
cd->cpumask = cpumask_of(cpu);
|
||||
cd->set_next_ktime = s390_next_ktime;
|
||||
cd->set_next_event = s390_next_event;
|
||||
cd->set_mode = s390_set_mode;
|
||||
|
||||
clockevents_register_device(cd);
|
||||
@ -221,21 +210,30 @@ struct clocksource * __init clocksource_default_clock(void)
|
||||
return &clocksource_tod;
|
||||
}
|
||||
|
||||
void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
|
||||
struct clocksource *clock, u32 mult)
|
||||
void update_vsyscall(struct timekeeper *tk)
|
||||
{
|
||||
if (clock != &clocksource_tod)
|
||||
u64 nsecps;
|
||||
|
||||
if (tk->clock != &clocksource_tod)
|
||||
return;
|
||||
|
||||
/* Make userspace gettimeofday spin until we're done. */
|
||||
++vdso_data->tb_update_count;
|
||||
smp_wmb();
|
||||
vdso_data->xtime_tod_stamp = clock->cycle_last;
|
||||
vdso_data->xtime_clock_sec = wall_time->tv_sec;
|
||||
vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
|
||||
vdso_data->wtom_clock_sec = wtm->tv_sec;
|
||||
vdso_data->wtom_clock_nsec = wtm->tv_nsec;
|
||||
vdso_data->ntp_mult = mult;
|
||||
vdso_data->xtime_tod_stamp = tk->clock->cycle_last;
|
||||
vdso_data->xtime_clock_sec = tk->xtime_sec;
|
||||
vdso_data->xtime_clock_nsec = tk->xtime_nsec;
|
||||
vdso_data->wtom_clock_sec =
|
||||
tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
|
||||
vdso_data->wtom_clock_nsec = tk->xtime_nsec +
|
||||
+ (tk->wall_to_monotonic.tv_nsec << tk->shift);
|
||||
nsecps = (u64) NSEC_PER_SEC << tk->shift;
|
||||
while (vdso_data->wtom_clock_nsec >= nsecps) {
|
||||
vdso_data->wtom_clock_nsec -= nsecps;
|
||||
vdso_data->wtom_clock_sec++;
|
||||
}
|
||||
vdso_data->tk_mult = tk->mult;
|
||||
vdso_data->tk_shift = tk->shift;
|
||||
smp_wmb();
|
||||
++vdso_data->tb_update_count;
|
||||
}
|
||||
|
@ -38,25 +38,26 @@ __kernel_clock_gettime:
|
||||
sl %r1,__VDSO_XTIME_STAMP+4(%r5)
|
||||
brc 3,2f
|
||||
ahi %r0,-1
|
||||
2: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
|
||||
2: ms %r0,__VDSO_TK_MULT(%r5) /* * tk->mult */
|
||||
lr %r2,%r0
|
||||
l %r0,__VDSO_NTP_MULT(%r5)
|
||||
l %r0,__VDSO_TK_MULT(%r5)
|
||||
ltr %r1,%r1
|
||||
mr %r0,%r0
|
||||
jnm 3f
|
||||
a %r0,__VDSO_NTP_MULT(%r5)
|
||||
a %r0,__VDSO_TK_MULT(%r5)
|
||||
3: alr %r0,%r2
|
||||
srdl %r0,12
|
||||
al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */
|
||||
al %r0,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
|
||||
al %r1,__VDSO_XTIME_NSEC+4(%r5)
|
||||
brc 12,4f
|
||||
ahi %r0,1
|
||||
4: l %r2,__VDSO_XTIME_SEC+4(%r5)
|
||||
al %r0,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic */
|
||||
4: al %r0,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic.nsec */
|
||||
al %r1,__VDSO_WTOM_NSEC+4(%r5)
|
||||
brc 12,5f
|
||||
ahi %r0,1
|
||||
5: al %r2,__VDSO_WTOM_SEC+4(%r5)
|
||||
5: l %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
|
||||
srdl %r0,0(%r2) /* >> tk->shift */
|
||||
l %r2,__VDSO_XTIME_SEC+4(%r5)
|
||||
al %r2,__VDSO_WTOM_SEC+4(%r5)
|
||||
cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */
|
||||
jne 1b
|
||||
basr %r5,0
|
||||
@ -86,20 +87,21 @@ __kernel_clock_gettime:
|
||||
sl %r1,__VDSO_XTIME_STAMP+4(%r5)
|
||||
brc 3,12f
|
||||
ahi %r0,-1
|
||||
12: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
|
||||
12: ms %r0,__VDSO_TK_MULT(%r5) /* * tk->mult */
|
||||
lr %r2,%r0
|
||||
l %r0,__VDSO_NTP_MULT(%r5)
|
||||
l %r0,__VDSO_TK_MULT(%r5)
|
||||
ltr %r1,%r1
|
||||
mr %r0,%r0
|
||||
jnm 13f
|
||||
a %r0,__VDSO_NTP_MULT(%r5)
|
||||
a %r0,__VDSO_TK_MULT(%r5)
|
||||
13: alr %r0,%r2
|
||||
srdl %r0,12
|
||||
al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */
|
||||
al %r0,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
|
||||
al %r1,__VDSO_XTIME_NSEC+4(%r5)
|
||||
brc 12,14f
|
||||
ahi %r0,1
|
||||
14: l %r2,__VDSO_XTIME_SEC+4(%r5)
|
||||
14: l %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
|
||||
srdl %r0,0(%r2) /* >> tk->shift */
|
||||
l %r2,__VDSO_XTIME_SEC+4(%r5)
|
||||
cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */
|
||||
jne 11b
|
||||
basr %r5,0
|
||||
|
@ -35,15 +35,14 @@ __kernel_gettimeofday:
|
||||
sl %r1,__VDSO_XTIME_STAMP+4(%r5)
|
||||
brc 3,3f
|
||||
ahi %r0,-1
|
||||
3: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
|
||||
3: ms %r0,__VDSO_TK_MULT(%r5) /* * tk->mult */
|
||||
st %r0,24(%r15)
|
||||
l %r0,__VDSO_NTP_MULT(%r5)
|
||||
l %r0,__VDSO_TK_MULT(%r5)
|
||||
ltr %r1,%r1
|
||||
mr %r0,%r0
|
||||
jnm 4f
|
||||
a %r0,__VDSO_NTP_MULT(%r5)
|
||||
a %r0,__VDSO_TK_MULT(%r5)
|
||||
4: al %r0,24(%r15)
|
||||
srdl %r0,12
|
||||
al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */
|
||||
al %r1,__VDSO_XTIME_NSEC+4(%r5)
|
||||
brc 12,5f
|
||||
@ -51,6 +50,8 @@ __kernel_gettimeofday:
|
||||
5: mvc 24(4,%r15),__VDSO_XTIME_SEC+4(%r5)
|
||||
cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */
|
||||
jne 1b
|
||||
l %r4,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
|
||||
srdl %r0,0(%r4) /* >> tk->shift */
|
||||
l %r4,24(%r15) /* get tv_sec from stack */
|
||||
basr %r5,0
|
||||
6: ltr %r0,%r0
|
||||
|
@ -34,14 +34,15 @@ __kernel_clock_gettime:
|
||||
tmll %r4,0x0001 /* pending update ? loop */
|
||||
jnz 0b
|
||||
stck 48(%r15) /* Store TOD clock */
|
||||
lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
|
||||
lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
|
||||
alg %r0,__VDSO_WTOM_SEC(%r5) /* + wall_to_monotonic.sec */
|
||||
lg %r1,48(%r15)
|
||||
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
|
||||
msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
|
||||
srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
|
||||
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */
|
||||
lg %r0,__VDSO_XTIME_SEC(%r5)
|
||||
alg %r1,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic */
|
||||
alg %r0,__VDSO_WTOM_SEC(%r5)
|
||||
msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
|
||||
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
|
||||
alg %r1,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic.nsec */
|
||||
srlg %r1,%r1,0(%r2) /* >> tk->shift */
|
||||
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
|
||||
jne 0b
|
||||
larl %r5,13f
|
||||
@ -62,12 +63,13 @@ __kernel_clock_gettime:
|
||||
tmll %r4,0x0001 /* pending update ? loop */
|
||||
jnz 5b
|
||||
stck 48(%r15) /* Store TOD clock */
|
||||
lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
|
||||
lg %r1,48(%r15)
|
||||
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
|
||||
msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
|
||||
srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
|
||||
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */
|
||||
lg %r0,__VDSO_XTIME_SEC(%r5)
|
||||
msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
|
||||
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
|
||||
srlg %r1,%r1,0(%r2) /* >> tk->shift */
|
||||
lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
|
||||
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
|
||||
jne 5b
|
||||
larl %r5,13f
|
||||
|
@ -31,12 +31,13 @@ __kernel_gettimeofday:
|
||||
stck 48(%r15) /* Store TOD clock */
|
||||
lg %r1,48(%r15)
|
||||
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
|
||||
msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
|
||||
srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
|
||||
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime.tv_nsec */
|
||||
lg %r0,__VDSO_XTIME_SEC(%r5) /* xtime.tv_sec */
|
||||
msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
|
||||
alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
|
||||
lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
|
||||
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
|
||||
jne 0b
|
||||
lgf %r5,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
|
||||
srlg %r1,%r1,0(%r5) /* >> tk->shift */
|
||||
larl %r5,5f
|
||||
2: clg %r1,0(%r5)
|
||||
jl 3f
|
||||
|
@ -78,11 +78,14 @@ static size_t copy_in_kernel(size_t count, void __user *to,
|
||||
* contains the (negative) exception code.
|
||||
*/
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
static unsigned long follow_table(struct mm_struct *mm,
|
||||
unsigned long address, int write)
|
||||
{
|
||||
unsigned long *table = (unsigned long *)__pa(mm->pgd);
|
||||
|
||||
if (unlikely(address > mm->context.asce_limit - 1))
|
||||
return -0x38UL;
|
||||
switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
|
||||
case _ASCE_TYPE_REGION1:
|
||||
table = table + ((address >> 53) & 0x7ff);
|
||||
|
@ -3,8 +3,9 @@
|
||||
#
|
||||
|
||||
avx_supported := $(call as-instr,vpxor %xmm0$(comma)%xmm0$(comma)%xmm0,yes,no)
|
||||
avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\
|
||||
$(comma)4)$(comma)%ymm2,yes,no)
|
||||
|
||||
obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o
|
||||
obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/i387.h>
|
||||
#include <asm/crypto/aes.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/internal/aead.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/ctr.h>
|
||||
#include <crypto/lrw.h>
|
||||
@ -21,7 +22,6 @@
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
#include <asm/crypto/camellia.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
|
||||
#define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/ctr.h>
|
||||
#include <crypto/lrw.h>
|
||||
@ -21,7 +22,6 @@
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
#include <asm/crypto/camellia.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
|
||||
#define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
|
||||
|
@ -26,13 +26,13 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/cast5.h>
|
||||
#include <crypto/cryptd.h>
|
||||
#include <crypto/ctr.h>
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
|
||||
#define CAST5_PARALLEL_BLOCKS 16
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/cast6.h>
|
||||
#include <crypto/cryptd.h>
|
||||
@ -37,7 +38,6 @@
|
||||
#include <crypto/xts.h>
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
|
||||
#define CAST6_PARALLEL_BLOCKS 8
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/ctr.h>
|
||||
#include <crypto/lrw.h>
|
||||
@ -22,7 +23,6 @@
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
#include <asm/crypto/serpent-avx.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
|
||||
#define SERPENT_AVX2_PARALLEL_BLOCKS 16
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/serpent.h>
|
||||
#include <crypto/cryptd.h>
|
||||
@ -38,7 +39,6 @@
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
#include <asm/crypto/serpent-avx.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
|
||||
/* 8-way parallel cipher functions */
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/serpent.h>
|
||||
#include <crypto/cryptd.h>
|
||||
@ -42,7 +43,6 @@
|
||||
#include <crypto/lrw.h>
|
||||
#include <crypto/xts.h>
|
||||
#include <asm/crypto/serpent-sse2.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
|
||||
static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
|
||||
|
@ -281,7 +281,7 @@ static int __init sha256_ssse3_mod_init(void)
|
||||
/* allow AVX to override SSSE3, it's a little faster */
|
||||
if (avx_usable()) {
|
||||
#ifdef CONFIG_AS_AVX2
|
||||
if (boot_cpu_has(X86_FEATURE_AVX2))
|
||||
if (boot_cpu_has(X86_FEATURE_AVX2) && boot_cpu_has(X86_FEATURE_BMI2))
|
||||
sha256_transform_asm = sha256_transform_rorx;
|
||||
else
|
||||
#endif
|
||||
@ -319,4 +319,4 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated");
|
||||
|
||||
MODULE_ALIAS("sha256");
|
||||
MODULE_ALIAS("sha384");
|
||||
MODULE_ALIAS("sha224");
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/twofish.h>
|
||||
#include <crypto/cryptd.h>
|
||||
@ -39,7 +40,6 @@
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
#include <asm/crypto/twofish.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <asm/crypto/glue_helper.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
11
arch/x86/include/asm/simd.h
Normal file
11
arch/x86/include/asm/simd.h
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
#include <asm/i387.h>
|
||||
|
||||
/*
|
||||
* may_use_simd - whether it is allowable at this time to issue SIMD
|
||||
* instructions or access the SIMD register file
|
||||
*/
|
||||
static __must_check inline bool may_use_simd(void)
|
||||
{
|
||||
return irq_fpu_usable();
|
||||
}
|
@ -174,9 +174,8 @@ config CRYPTO_TEST
|
||||
help
|
||||
Quick & dirty crypto test module.
|
||||
|
||||
config CRYPTO_ABLK_HELPER_X86
|
||||
config CRYPTO_ABLK_HELPER
|
||||
tristate
|
||||
depends on X86
|
||||
select CRYPTO_CRYPTD
|
||||
|
||||
config CRYPTO_GLUE_HELPER_X86
|
||||
@ -695,7 +694,7 @@ config CRYPTO_AES_NI_INTEL
|
||||
select CRYPTO_AES_X86_64 if 64BIT
|
||||
select CRYPTO_AES_586 if !64BIT
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_GLUE_HELPER_X86 if 64BIT
|
||||
select CRYPTO_LRW
|
||||
@ -895,7 +894,7 @@ config CRYPTO_CAMELLIA_AESNI_AVX_X86_64
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_CAMELLIA_X86_64
|
||||
select CRYPTO_LRW
|
||||
@ -917,7 +916,7 @@ config CRYPTO_CAMELLIA_AESNI_AVX2_X86_64
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_CAMELLIA_X86_64
|
||||
select CRYPTO_CAMELLIA_AESNI_AVX_X86_64
|
||||
@ -969,7 +968,7 @@ config CRYPTO_CAST5_AVX_X86_64
|
||||
depends on X86 && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_CAST_COMMON
|
||||
select CRYPTO_CAST5
|
||||
help
|
||||
@ -992,7 +991,7 @@ config CRYPTO_CAST6_AVX_X86_64
|
||||
depends on X86 && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_CAST_COMMON
|
||||
select CRYPTO_CAST6
|
||||
@ -1110,7 +1109,7 @@ config CRYPTO_SERPENT_SSE2_X86_64
|
||||
depends on X86 && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_SERPENT
|
||||
select CRYPTO_LRW
|
||||
@ -1132,7 +1131,7 @@ config CRYPTO_SERPENT_SSE2_586
|
||||
depends on X86 && !64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_SERPENT
|
||||
select CRYPTO_LRW
|
||||
@ -1154,7 +1153,7 @@ config CRYPTO_SERPENT_AVX_X86_64
|
||||
depends on X86 && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_SERPENT
|
||||
select CRYPTO_LRW
|
||||
@ -1176,7 +1175,7 @@ config CRYPTO_SERPENT_AVX2_X86_64
|
||||
depends on X86 && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_SERPENT
|
||||
select CRYPTO_SERPENT_AVX_X86_64
|
||||
@ -1292,7 +1291,7 @@ config CRYPTO_TWOFISH_AVX_X86_64
|
||||
depends on X86 && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_ABLK_HELPER_X86
|
||||
select CRYPTO_ABLK_HELPER
|
||||
select CRYPTO_GLUE_HELPER_X86
|
||||
select CRYPTO_TWOFISH_COMMON
|
||||
select CRYPTO_TWOFISH_X86_64
|
||||
|
@ -2,8 +2,13 @@
|
||||
# Cryptographic API
|
||||
#
|
||||
|
||||
# memneq MUST be built with -Os or -O0 to prevent early-return optimizations
|
||||
# that will defeat memneq's actual purpose to prevent timing attacks.
|
||||
CFLAGS_REMOVE_memneq.o := -O1 -O2 -O3
|
||||
CFLAGS_memneq.o := -Os
|
||||
|
||||
obj-$(CONFIG_CRYPTO) += crypto.o
|
||||
crypto-y := api.o cipher.o compress.o
|
||||
crypto-y := api.o cipher.o compress.o memneq.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o
|
||||
|
||||
@ -105,3 +110,4 @@ obj-$(CONFIG_XOR_BLOCKS) += xor.o
|
||||
obj-$(CONFIG_ASYNC_CORE) += async_tx/
|
||||
obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
|
||||
obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
|
||||
obj-$(CONFIG_CRYPTO_ABLK_HELPER) += ablk_helper.o
|
||||
|
@ -28,10 +28,11 @@
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/cryptd.h>
|
||||
#include <asm/i387.h>
|
||||
#include <asm/crypto/ablk_helper.h>
|
||||
#include <crypto/ablk_helper.h>
|
||||
#include <asm/simd.h>
|
||||
|
||||
int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
@ -70,11 +71,11 @@ int ablk_encrypt(struct ablkcipher_request *req)
|
||||
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
|
||||
struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
|
||||
|
||||
if (!irq_fpu_usable()) {
|
||||
if (!may_use_simd()) {
|
||||
struct ablkcipher_request *cryptd_req =
|
||||
ablkcipher_request_ctx(req);
|
||||
|
||||
memcpy(cryptd_req, req, sizeof(*req));
|
||||
*cryptd_req = *req;
|
||||
ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
|
||||
|
||||
return crypto_ablkcipher_encrypt(cryptd_req);
|
||||
@ -89,11 +90,11 @@ int ablk_decrypt(struct ablkcipher_request *req)
|
||||
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
|
||||
struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
|
||||
|
||||
if (!irq_fpu_usable()) {
|
||||
if (!may_use_simd()) {
|
||||
struct ablkcipher_request *cryptd_req =
|
||||
ablkcipher_request_ctx(req);
|
||||
|
||||
memcpy(cryptd_req, req, sizeof(*req));
|
||||
*cryptd_req = *req;
|
||||
ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
|
||||
|
||||
return crypto_ablkcipher_decrypt(cryptd_req);
|
@ -16,9 +16,7 @@
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
@ -30,8 +28,6 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static const char *skcipher_default_geniv __read_mostly;
|
||||
|
||||
struct ablkcipher_buffer {
|
||||
struct list_head entry;
|
||||
struct scatter_walk dst;
|
||||
@ -527,8 +523,7 @@ const char *crypto_default_geniv(const struct crypto_alg *alg)
|
||||
alg->cra_blocksize)
|
||||
return "chainiv";
|
||||
|
||||
return alg->cra_flags & CRYPTO_ALG_ASYNC ?
|
||||
"eseqiv" : skcipher_default_geniv;
|
||||
return "eseqiv";
|
||||
}
|
||||
|
||||
static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
|
||||
@ -709,17 +704,3 @@ err:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher);
|
||||
|
||||
static int __init skcipher_module_init(void)
|
||||
{
|
||||
skcipher_default_geniv = num_possible_cpus() > 1 ?
|
||||
"eseqiv" : "chainiv";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void skcipher_module_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(skcipher_module_init);
|
||||
module_exit(skcipher_module_exit);
|
||||
|
@ -230,11 +230,11 @@ remainder:
|
||||
*/
|
||||
if (byte_count < DEFAULT_BLK_SZ) {
|
||||
empty_rbuf:
|
||||
for (; ctx->rand_data_valid < DEFAULT_BLK_SZ;
|
||||
ctx->rand_data_valid++) {
|
||||
while (ctx->rand_data_valid < DEFAULT_BLK_SZ) {
|
||||
*ptr = ctx->rand_data[ctx->rand_data_valid];
|
||||
ptr++;
|
||||
byte_count--;
|
||||
ctx->rand_data_valid++;
|
||||
if (byte_count == 0)
|
||||
goto done;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include "public_key.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -189,12 +190,12 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) {
|
||||
if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
|
||||
kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) {
|
||||
if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
|
||||
kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
|
||||
return -EKEYREJECTED;
|
||||
}
|
||||
|
@ -18,59 +18,11 @@
|
||||
#include <linux/asn1_decoder.h>
|
||||
#include <keys/asymmetric-subtype.h>
|
||||
#include <keys/asymmetric-parser.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include <crypto/hash.h>
|
||||
#include "asymmetric_keys.h"
|
||||
#include "public_key.h"
|
||||
#include "x509_parser.h"
|
||||
|
||||
/*
|
||||
* Find a key in the given keyring by issuer and authority.
|
||||
*/
|
||||
static struct key *x509_request_asymmetric_key(
|
||||
struct key *keyring,
|
||||
const char *signer, size_t signer_len,
|
||||
const char *authority, size_t auth_len)
|
||||
{
|
||||
key_ref_t key;
|
||||
char *id;
|
||||
|
||||
/* Construct an identifier. */
|
||||
id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL);
|
||||
if (!id)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(id, signer, signer_len);
|
||||
id[signer_len + 0] = ':';
|
||||
id[signer_len + 1] = ' ';
|
||||
memcpy(id + signer_len + 2, authority, auth_len);
|
||||
id[signer_len + 2 + auth_len] = 0;
|
||||
|
||||
pr_debug("Look up: \"%s\"\n", id);
|
||||
|
||||
key = keyring_search(make_key_ref(keyring, 1),
|
||||
&key_type_asymmetric, id);
|
||||
if (IS_ERR(key))
|
||||
pr_debug("Request for module key '%s' err %ld\n",
|
||||
id, PTR_ERR(key));
|
||||
kfree(id);
|
||||
|
||||
if (IS_ERR(key)) {
|
||||
switch (PTR_ERR(key)) {
|
||||
/* Hide some search errors */
|
||||
case -EACCES:
|
||||
case -ENOTDIR:
|
||||
case -EAGAIN:
|
||||
return ERR_PTR(-ENOKEY);
|
||||
default:
|
||||
return ERR_CAST(key);
|
||||
}
|
||||
}
|
||||
|
||||
pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
|
||||
return key_ref_to_ptr(key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the signature parameters in an X.509 certificate. This involves
|
||||
* digesting the signed data and extracting the signature.
|
||||
@ -150,33 +102,6 @@ int x509_check_signature(const struct public_key *pub,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(x509_check_signature);
|
||||
|
||||
/*
|
||||
* Check the new certificate against the ones in the trust keyring. If one of
|
||||
* those is the signing key and validates the new certificate, then mark the
|
||||
* new certificate as being trusted.
|
||||
*
|
||||
* Return 0 if the new certificate was successfully validated, 1 if we couldn't
|
||||
* find a matching parent certificate in the trusted list and an error if there
|
||||
* is a matching certificate but the signature check fails.
|
||||
*/
|
||||
static int x509_validate_trust(struct x509_certificate *cert,
|
||||
struct key *trust_keyring)
|
||||
{
|
||||
const struct public_key *pk;
|
||||
struct key *key;
|
||||
int ret = 1;
|
||||
|
||||
key = x509_request_asymmetric_key(trust_keyring,
|
||||
cert->issuer, strlen(cert->issuer),
|
||||
cert->authority,
|
||||
strlen(cert->authority));
|
||||
if (!IS_ERR(key)) {
|
||||
pk = key->payload.data;
|
||||
ret = x509_check_signature(pk, cert);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse a data blob for a key as an X509 certificate.
|
||||
*/
|
||||
@ -230,13 +155,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
|
||||
/* Check the signature on the key if it appears to be self-signed */
|
||||
if (!cert->authority ||
|
||||
strcmp(cert->fingerprint, cert->authority) == 0) {
|
||||
ret = x509_check_signature(cert->pub, cert); /* self-signed */
|
||||
ret = x509_check_signature(cert->pub, cert);
|
||||
if (ret < 0)
|
||||
goto error_free_cert;
|
||||
} else {
|
||||
ret = x509_validate_trust(cert, system_trusted_keyring);
|
||||
if (!ret)
|
||||
prep->trusted = 1;
|
||||
}
|
||||
|
||||
/* Propose a description */
|
||||
|
@ -52,40 +52,52 @@ static void authenc_request_complete(struct aead_request *req, int err)
|
||||
aead_request_complete(req, err);
|
||||
}
|
||||
|
||||
static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
|
||||
unsigned int keylen)
|
||||
int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
unsigned int authkeylen;
|
||||
unsigned int enckeylen;
|
||||
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
|
||||
struct crypto_ahash *auth = ctx->auth;
|
||||
struct crypto_ablkcipher *enc = ctx->enc;
|
||||
struct rtattr *rta = (void *)key;
|
||||
struct rtattr *rta = (struct rtattr *)key;
|
||||
struct crypto_authenc_key_param *param;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (!RTA_OK(rta, keylen))
|
||||
goto badkey;
|
||||
return -EINVAL;
|
||||
if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
|
||||
goto badkey;
|
||||
return -EINVAL;
|
||||
if (RTA_PAYLOAD(rta) < sizeof(*param))
|
||||
goto badkey;
|
||||
return -EINVAL;
|
||||
|
||||
param = RTA_DATA(rta);
|
||||
enckeylen = be32_to_cpu(param->enckeylen);
|
||||
keys->enckeylen = be32_to_cpu(param->enckeylen);
|
||||
|
||||
key += RTA_ALIGN(rta->rta_len);
|
||||
keylen -= RTA_ALIGN(rta->rta_len);
|
||||
|
||||
if (keylen < enckeylen)
|
||||
goto badkey;
|
||||
if (keylen < keys->enckeylen)
|
||||
return -EINVAL;
|
||||
|
||||
authkeylen = keylen - enckeylen;
|
||||
keys->authkeylen = keylen - keys->enckeylen;
|
||||
keys->authkey = key;
|
||||
keys->enckey = key + keys->authkeylen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_authenc_extractkeys);
|
||||
|
||||
static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
|
||||
struct crypto_ahash *auth = ctx->auth;
|
||||
struct crypto_ablkcipher *enc = ctx->enc;
|
||||
struct crypto_authenc_keys keys;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
|
||||
goto badkey;
|
||||
|
||||
crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
|
||||
crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc) &
|
||||
CRYPTO_TFM_REQ_MASK);
|
||||
err = crypto_ahash_setkey(auth, key, authkeylen);
|
||||
err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen);
|
||||
crypto_aead_set_flags(authenc, crypto_ahash_get_flags(auth) &
|
||||
CRYPTO_TFM_RES_MASK);
|
||||
|
||||
@ -95,7 +107,7 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
|
||||
crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
|
||||
crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) &
|
||||
CRYPTO_TFM_REQ_MASK);
|
||||
err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
|
||||
err = crypto_ablkcipher_setkey(enc, keys.enckey, keys.enckeylen);
|
||||
crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) &
|
||||
CRYPTO_TFM_RES_MASK);
|
||||
|
||||
@ -188,7 +200,7 @@ static void authenc_verify_ahash_update_done(struct crypto_async_request *areq,
|
||||
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
|
||||
authsize, 0);
|
||||
|
||||
err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -227,7 +239,7 @@ static void authenc_verify_ahash_done(struct crypto_async_request *areq,
|
||||
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
|
||||
authsize, 0);
|
||||
|
||||
err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -462,7 +474,7 @@ static int crypto_authenc_verify(struct aead_request *req,
|
||||
ihash = ohash + authsize;
|
||||
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
|
||||
authsize, 0);
|
||||
return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
|
||||
return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
|
||||
}
|
||||
|
||||
static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
|
||||
|
@ -59,37 +59,19 @@ static void authenc_esn_request_complete(struct aead_request *req, int err)
|
||||
static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
unsigned int authkeylen;
|
||||
unsigned int enckeylen;
|
||||
struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
|
||||
struct crypto_ahash *auth = ctx->auth;
|
||||
struct crypto_ablkcipher *enc = ctx->enc;
|
||||
struct rtattr *rta = (void *)key;
|
||||
struct crypto_authenc_key_param *param;
|
||||
struct crypto_authenc_keys keys;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (!RTA_OK(rta, keylen))
|
||||
if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
|
||||
goto badkey;
|
||||
if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
|
||||
goto badkey;
|
||||
if (RTA_PAYLOAD(rta) < sizeof(*param))
|
||||
goto badkey;
|
||||
|
||||
param = RTA_DATA(rta);
|
||||
enckeylen = be32_to_cpu(param->enckeylen);
|
||||
|
||||
key += RTA_ALIGN(rta->rta_len);
|
||||
keylen -= RTA_ALIGN(rta->rta_len);
|
||||
|
||||
if (keylen < enckeylen)
|
||||
goto badkey;
|
||||
|
||||
authkeylen = keylen - enckeylen;
|
||||
|
||||
crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
|
||||
crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
|
||||
CRYPTO_TFM_REQ_MASK);
|
||||
err = crypto_ahash_setkey(auth, key, authkeylen);
|
||||
err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen);
|
||||
crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
|
||||
CRYPTO_TFM_RES_MASK);
|
||||
|
||||
@ -99,7 +81,7 @@ static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *
|
||||
crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
|
||||
crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
|
||||
CRYPTO_TFM_REQ_MASK);
|
||||
err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
|
||||
err = crypto_ablkcipher_setkey(enc, keys.enckey, keys.enckeylen);
|
||||
crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) &
|
||||
CRYPTO_TFM_RES_MASK);
|
||||
|
||||
@ -247,7 +229,7 @@ static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *ar
|
||||
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
|
||||
authsize, 0);
|
||||
|
||||
err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -296,7 +278,7 @@ static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *a
|
||||
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
|
||||
authsize, 0);
|
||||
|
||||
err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -336,7 +318,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
|
||||
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
|
||||
authsize, 0);
|
||||
|
||||
err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -568,7 +550,7 @@ static int crypto_authenc_esn_verify(struct aead_request *req)
|
||||
ihash = ohash + authsize;
|
||||
scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
|
||||
authsize, 0);
|
||||
return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
|
||||
return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
|
||||
}
|
||||
|
||||
static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
|
||||
|
@ -363,7 +363,7 @@ static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
|
||||
|
||||
if (!err) {
|
||||
err = crypto_ccm_auth(req, req->dst, cryptlen);
|
||||
if (!err && memcmp(pctx->auth_tag, pctx->odata, authsize))
|
||||
if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
|
||||
err = -EBADMSG;
|
||||
}
|
||||
aead_request_complete(req, err);
|
||||
@ -422,7 +422,7 @@ static int crypto_ccm_decrypt(struct aead_request *req)
|
||||
return err;
|
||||
|
||||
/* verify */
|
||||
if (memcmp(authtag, odata, authsize))
|
||||
if (crypto_memneq(authtag, odata, authsize))
|
||||
return -EBADMSG;
|
||||
|
||||
return err;
|
||||
|
@ -582,7 +582,7 @@ static int crypto_gcm_verify(struct aead_request *req,
|
||||
|
||||
crypto_xor(auth_tag, iauth_tag, 16);
|
||||
scatterwalk_map_and_copy(iauth_tag, req->src, cryptlen, authsize, 0);
|
||||
return memcmp(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
|
||||
return crypto_memneq(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
|
||||
}
|
||||
|
||||
static void gcm_decrypt_done(struct crypto_async_request *areq, int err)
|
||||
|
138
crypto/memneq.c
Normal file
138
crypto/memneq.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Constant-time equality testing of memory regions.
|
||||
*
|
||||
* Authors:
|
||||
*
|
||||
* James Yonan <james@openvpn.net>
|
||||
* Daniel Borkmann <dborkman@redhat.com>
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2013 OpenVPN Technologies, Inc. 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 OpenVPN Technologies 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 AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE 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.
|
||||
*/
|
||||
|
||||
#include <crypto/algapi.h>
|
||||
|
||||
#ifndef __HAVE_ARCH_CRYPTO_MEMNEQ
|
||||
|
||||
/* Generic path for arbitrary size */
|
||||
static inline unsigned long
|
||||
__crypto_memneq_generic(const void *a, const void *b, size_t size)
|
||||
{
|
||||
unsigned long neq = 0;
|
||||
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
while (size >= sizeof(unsigned long)) {
|
||||
neq |= *(unsigned long *)a ^ *(unsigned long *)b;
|
||||
a += sizeof(unsigned long);
|
||||
b += sizeof(unsigned long);
|
||||
size -= sizeof(unsigned long);
|
||||
}
|
||||
#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
|
||||
while (size > 0) {
|
||||
neq |= *(unsigned char *)a ^ *(unsigned char *)b;
|
||||
a += 1;
|
||||
b += 1;
|
||||
size -= 1;
|
||||
}
|
||||
return neq;
|
||||
}
|
||||
|
||||
/* Loop-free fast-path for frequently used 16-byte size */
|
||||
static inline unsigned long __crypto_memneq_16(const void *a, const void *b)
|
||||
{
|
||||
#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
if (sizeof(unsigned long) == 8)
|
||||
return ((*(unsigned long *)(a) ^ *(unsigned long *)(b))
|
||||
| (*(unsigned long *)(a+8) ^ *(unsigned long *)(b+8)));
|
||||
else if (sizeof(unsigned int) == 4)
|
||||
return ((*(unsigned int *)(a) ^ *(unsigned int *)(b))
|
||||
| (*(unsigned int *)(a+4) ^ *(unsigned int *)(b+4))
|
||||
| (*(unsigned int *)(a+8) ^ *(unsigned int *)(b+8))
|
||||
| (*(unsigned int *)(a+12) ^ *(unsigned int *)(b+12)));
|
||||
else
|
||||
#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
|
||||
return ((*(unsigned char *)(a) ^ *(unsigned char *)(b))
|
||||
| (*(unsigned char *)(a+1) ^ *(unsigned char *)(b+1))
|
||||
| (*(unsigned char *)(a+2) ^ *(unsigned char *)(b+2))
|
||||
| (*(unsigned char *)(a+3) ^ *(unsigned char *)(b+3))
|
||||
| (*(unsigned char *)(a+4) ^ *(unsigned char *)(b+4))
|
||||
| (*(unsigned char *)(a+5) ^ *(unsigned char *)(b+5))
|
||||
| (*(unsigned char *)(a+6) ^ *(unsigned char *)(b+6))
|
||||
| (*(unsigned char *)(a+7) ^ *(unsigned char *)(b+7))
|
||||
| (*(unsigned char *)(a+8) ^ *(unsigned char *)(b+8))
|
||||
| (*(unsigned char *)(a+9) ^ *(unsigned char *)(b+9))
|
||||
| (*(unsigned char *)(a+10) ^ *(unsigned char *)(b+10))
|
||||
| (*(unsigned char *)(a+11) ^ *(unsigned char *)(b+11))
|
||||
| (*(unsigned char *)(a+12) ^ *(unsigned char *)(b+12))
|
||||
| (*(unsigned char *)(a+13) ^ *(unsigned char *)(b+13))
|
||||
| (*(unsigned char *)(a+14) ^ *(unsigned char *)(b+14))
|
||||
| (*(unsigned char *)(a+15) ^ *(unsigned char *)(b+15)));
|
||||
}
|
||||
|
||||
/* Compare two areas of memory without leaking timing information,
|
||||
* and with special optimizations for common sizes. Users should
|
||||
* not call this function directly, but should instead use
|
||||
* crypto_memneq defined in crypto/algapi.h.
|
||||
*/
|
||||
noinline unsigned long __crypto_memneq(const void *a, const void *b,
|
||||
size_t size)
|
||||
{
|
||||
switch (size) {
|
||||
case 16:
|
||||
return __crypto_memneq_16(a, b);
|
||||
default:
|
||||
return __crypto_memneq_generic(a, b, size);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(__crypto_memneq);
|
||||
|
||||
#endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */
|
@ -184,7 +184,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
|
||||
struct acpi_buffer *output_buffer);
|
||||
|
||||
acpi_status
|
||||
acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
|
||||
acpi_rs_create_aml_resources(struct acpi_buffer *resource_list,
|
||||
struct acpi_buffer *output_buffer);
|
||||
|
||||
acpi_status
|
||||
@ -227,8 +227,8 @@ acpi_rs_get_list_length(u8 * aml_buffer,
|
||||
u32 aml_buffer_length, acpi_size * size_needed);
|
||||
|
||||
acpi_status
|
||||
acpi_rs_get_aml_length(struct acpi_resource *linked_list_buffer,
|
||||
acpi_size * size_needed);
|
||||
acpi_rs_get_aml_length(struct acpi_resource *resource_list,
|
||||
acpi_size resource_list_size, acpi_size * size_needed);
|
||||
|
||||
acpi_status
|
||||
acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
|
||||
|
@ -106,6 +106,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name)
|
||||
void acpi_ns_delete_node(struct acpi_namespace_node *node)
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
union acpi_operand_object *next_desc;
|
||||
|
||||
ACPI_FUNCTION_NAME(ns_delete_node);
|
||||
|
||||
@ -114,12 +115,13 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
|
||||
acpi_ns_detach_object(node);
|
||||
|
||||
/*
|
||||
* Delete an attached data object if present (an object that was created
|
||||
* and attached via acpi_attach_data). Note: After any normal object is
|
||||
* detached above, the only possible remaining object is a data object.
|
||||
* Delete an attached data object list if present (objects that were
|
||||
* attached via acpi_attach_data). Note: After any normal object is
|
||||
* detached above, the only possible remaining object(s) are data
|
||||
* objects, in a linked list.
|
||||
*/
|
||||
obj_desc = node->object;
|
||||
if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
|
||||
while (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
|
||||
|
||||
/* Invoke the attached data deletion handler if present */
|
||||
|
||||
@ -127,7 +129,15 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
|
||||
obj_desc->data.handler(node, obj_desc->data.pointer);
|
||||
}
|
||||
|
||||
next_desc = obj_desc->common.next_object;
|
||||
acpi_ut_remove_reference(obj_desc);
|
||||
obj_desc = next_desc;
|
||||
}
|
||||
|
||||
/* Special case for the statically allocated root node */
|
||||
|
||||
if (node == acpi_gbl_root_node) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now we can delete the node */
|
||||
|
@ -593,24 +593,26 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
|
||||
|
||||
void acpi_ns_terminate(void)
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_terminate);
|
||||
|
||||
/*
|
||||
* 1) Free the entire namespace -- all nodes and objects
|
||||
*
|
||||
* Delete all object descriptors attached to namepsace nodes
|
||||
* Free the entire namespace -- all nodes and all objects
|
||||
* attached to the nodes
|
||||
*/
|
||||
acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
|
||||
|
||||
/* Detach any objects attached to the root */
|
||||
/* Delete any objects attached to the root node */
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
|
||||
if (obj_desc) {
|
||||
acpi_ns_detach_object(acpi_gbl_root_node);
|
||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
acpi_ns_delete_node(acpi_gbl_root_node);
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
|
||||
return_VOID;
|
||||
}
|
||||
|
@ -174,6 +174,7 @@ acpi_rs_stream_option_length(u32 resource_length,
|
||||
* FUNCTION: acpi_rs_get_aml_length
|
||||
*
|
||||
* PARAMETERS: resource - Pointer to the resource linked list
|
||||
* resource_list_size - Size of the resource linked list
|
||||
* size_needed - Where the required size is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
@ -185,16 +186,20 @@ acpi_rs_stream_option_length(u32 resource_length,
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
|
||||
acpi_rs_get_aml_length(struct acpi_resource *resource,
|
||||
acpi_size resource_list_size, acpi_size * size_needed)
|
||||
{
|
||||
acpi_size aml_size_needed = 0;
|
||||
struct acpi_resource *resource_end;
|
||||
acpi_rs_length total_size;
|
||||
|
||||
ACPI_FUNCTION_TRACE(rs_get_aml_length);
|
||||
|
||||
/* Traverse entire list of internal resource descriptors */
|
||||
|
||||
while (resource) {
|
||||
resource_end =
|
||||
ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
|
||||
while (resource < resource_end) {
|
||||
|
||||
/* Validate the descriptor type */
|
||||
|
||||
|
@ -418,22 +418,21 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
|
||||
*
|
||||
* FUNCTION: acpi_rs_create_aml_resources
|
||||
*
|
||||
* PARAMETERS: linked_list_buffer - Pointer to the resource linked list
|
||||
* output_buffer - Pointer to the user's buffer
|
||||
* PARAMETERS: resource_list - Pointer to the resource list buffer
|
||||
* output_buffer - Where the AML buffer is returned
|
||||
*
|
||||
* RETURN: Status AE_OK if okay, else a valid acpi_status code.
|
||||
* If the output_buffer is too small, the error will be
|
||||
* AE_BUFFER_OVERFLOW and output_buffer->Length will point
|
||||
* to the size buffer needed.
|
||||
*
|
||||
* DESCRIPTION: Takes the linked list of device resources and
|
||||
* creates a bytestream to be used as input for the
|
||||
* _SRS control method.
|
||||
* DESCRIPTION: Converts a list of device resources to an AML bytestream
|
||||
* to be used as input for the _SRS control method.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
|
||||
acpi_rs_create_aml_resources(struct acpi_buffer *resource_list,
|
||||
struct acpi_buffer *output_buffer)
|
||||
{
|
||||
acpi_status status;
|
||||
@ -441,16 +440,16 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
|
||||
|
||||
ACPI_FUNCTION_TRACE(rs_create_aml_resources);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n",
|
||||
linked_list_buffer));
|
||||
/* Params already validated, no need to re-validate here */
|
||||
|
||||
/*
|
||||
* Params already validated, so we don't re-validate here
|
||||
*
|
||||
* Pass the linked_list_buffer into a module that calculates
|
||||
* the buffer size needed for the byte stream.
|
||||
*/
|
||||
status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed);
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ResourceList Buffer = %p\n",
|
||||
resource_list->pointer));
|
||||
|
||||
/* Get the buffer size needed for the AML byte stream */
|
||||
|
||||
status = acpi_rs_get_aml_length(resource_list->pointer,
|
||||
resource_list->length,
|
||||
&aml_size_needed);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
|
||||
(u32)aml_size_needed, acpi_format_exception(status)));
|
||||
@ -467,10 +466,9 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
|
||||
|
||||
/* Do the conversion */
|
||||
|
||||
status =
|
||||
acpi_rs_convert_resources_to_aml(linked_list_buffer,
|
||||
aml_size_needed,
|
||||
output_buffer->pointer);
|
||||
status = acpi_rs_convert_resources_to_aml(resource_list->pointer,
|
||||
aml_size_needed,
|
||||
output_buffer->pointer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user