mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 17:41:50 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/usb/r8152.c net/netfilter/nfnetlink.c Both r8152 and nfnetlink conflicts were simple overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
739e4a758e
129 changed files with 1539 additions and 950 deletions
|
@ -345,14 +345,14 @@ the named feature on.
|
||||||
The implementation is simple.
|
The implementation is simple.
|
||||||
|
|
||||||
Setting the flag 'cpuset.memory_spread_page' turns on a per-process flag
|
Setting the flag 'cpuset.memory_spread_page' turns on a per-process flag
|
||||||
PF_SPREAD_PAGE for each task that is in that cpuset or subsequently
|
PFA_SPREAD_PAGE for each task that is in that cpuset or subsequently
|
||||||
joins that cpuset. The page allocation calls for the page cache
|
joins that cpuset. The page allocation calls for the page cache
|
||||||
is modified to perform an inline check for this PF_SPREAD_PAGE task
|
is modified to perform an inline check for this PFA_SPREAD_PAGE task
|
||||||
flag, and if set, a call to a new routine cpuset_mem_spread_node()
|
flag, and if set, a call to a new routine cpuset_mem_spread_node()
|
||||||
returns the node to prefer for the allocation.
|
returns the node to prefer for the allocation.
|
||||||
|
|
||||||
Similarly, setting 'cpuset.memory_spread_slab' turns on the flag
|
Similarly, setting 'cpuset.memory_spread_slab' turns on the flag
|
||||||
PF_SPREAD_SLAB, and appropriately marked slab caches will allocate
|
PFA_SPREAD_SLAB, and appropriately marked slab caches will allocate
|
||||||
pages from the node returned by cpuset_mem_spread_node().
|
pages from the node returned by cpuset_mem_spread_node().
|
||||||
|
|
||||||
The cpuset_mem_spread_node() routine is also simple. It uses the
|
The cpuset_mem_spread_node() routine is also simple. It uses the
|
||||||
|
|
|
@ -56,6 +56,9 @@ Required properties:
|
||||||
- fsl,data-width : should be <18> or <24>
|
- fsl,data-width : should be <18> or <24>
|
||||||
- port: A port node with endpoint definitions as defined in
|
- port: A port node with endpoint definitions as defined in
|
||||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||||
|
On i.MX5, the internal two-input-multiplexer is used.
|
||||||
|
Due to hardware limitations, only one port (port@[0,1])
|
||||||
|
can be used for each channel (lvds-channel@[0,1], respectively)
|
||||||
On i.MX6, there should be four ports (port@[0-3]) that correspond
|
On i.MX6, there should be four ports (port@[0-3]) that correspond
|
||||||
to the four LVDS multiplexer inputs.
|
to the four LVDS multiplexer inputs.
|
||||||
|
|
||||||
|
@ -78,6 +81,8 @@ ldb: ldb@53fa8008 {
|
||||||
"di0", "di1";
|
"di0", "di1";
|
||||||
|
|
||||||
lvds-channel@0 {
|
lvds-channel@0 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
fsl,data-mapping = "spwg";
|
fsl,data-mapping = "spwg";
|
||||||
fsl,data-width = <24>;
|
fsl,data-width = <24>;
|
||||||
|
@ -86,7 +91,9 @@ ldb: ldb@53fa8008 {
|
||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
port {
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
lvds0_in: endpoint {
|
lvds0_in: endpoint {
|
||||||
remote-endpoint = <&ipu_di0_lvds0>;
|
remote-endpoint = <&ipu_di0_lvds0>;
|
||||||
};
|
};
|
||||||
|
@ -94,6 +101,8 @@ ldb: ldb@53fa8008 {
|
||||||
};
|
};
|
||||||
|
|
||||||
lvds-channel@1 {
|
lvds-channel@1 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
fsl,data-mapping = "spwg";
|
fsl,data-mapping = "spwg";
|
||||||
fsl,data-width = <24>;
|
fsl,data-width = <24>;
|
||||||
|
@ -102,7 +111,9 @@ ldb: ldb@53fa8008 {
|
||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
port {
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
|
||||||
lvds1_in: endpoint {
|
lvds1_in: endpoint {
|
||||||
remote-endpoint = <&ipu_di1_lvds1>;
|
remote-endpoint = <&ipu_di1_lvds1>;
|
||||||
};
|
};
|
||||||
|
|
211
Documentation/devicetree/of_selftest.txt
Normal file
211
Documentation/devicetree/of_selftest.txt
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
Open Firmware Device Tree Selftest
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Author: Gaurav Minocha <gaurav.minocha.os@gmail.com>
|
||||||
|
|
||||||
|
1. Introduction
|
||||||
|
|
||||||
|
This document explains how the test data required for executing OF selftest
|
||||||
|
is attached to the live tree dynamically, independent of the machine's
|
||||||
|
architecture.
|
||||||
|
|
||||||
|
It is recommended to read the following documents before moving ahead.
|
||||||
|
|
||||||
|
[1] Documentation/devicetree/usage-model.txt
|
||||||
|
[2] http://www.devicetree.org/Device_Tree_Usage
|
||||||
|
|
||||||
|
OF Selftest has been designed to test the interface (include/linux/of.h)
|
||||||
|
provided to device driver developers to fetch the device information..etc.
|
||||||
|
from the unflattened device tree data structure. This interface is used by
|
||||||
|
most of the device drivers in various use cases.
|
||||||
|
|
||||||
|
|
||||||
|
2. Test-data
|
||||||
|
|
||||||
|
The Device Tree Source file (drivers/of/testcase-data/testcases.dts) contains
|
||||||
|
the test data required for executing the unit tests automated in
|
||||||
|
drivers/of/selftests.c. Currently, following Device Tree Source Include files
|
||||||
|
(.dtsi) are included in testcase.dts:
|
||||||
|
|
||||||
|
drivers/of/testcase-data/tests-interrupts.dtsi
|
||||||
|
drivers/of/testcase-data/tests-platform.dtsi
|
||||||
|
drivers/of/testcase-data/tests-phandle.dtsi
|
||||||
|
drivers/of/testcase-data/tests-match.dtsi
|
||||||
|
|
||||||
|
When the kernel is build with OF_SELFTEST enabled, then the following make rule
|
||||||
|
|
||||||
|
$(obj)/%.dtb: $(src)/%.dts FORCE
|
||||||
|
$(call if_changed_dep, dtc)
|
||||||
|
|
||||||
|
is used to compile the DT source file (testcase.dts) into a binary blob
|
||||||
|
(testcase.dtb), also referred as flattened DT.
|
||||||
|
|
||||||
|
After that, using the following rule the binary blob above is wrapped as an
|
||||||
|
assembly file (testcase.dtb.S).
|
||||||
|
|
||||||
|
$(obj)/%.dtb.S: $(obj)/%.dtb
|
||||||
|
$(call cmd, dt_S_dtb)
|
||||||
|
|
||||||
|
The assembly file is compiled into an object file (testcase.dtb.o), and is
|
||||||
|
linked into the kernel image.
|
||||||
|
|
||||||
|
|
||||||
|
2.1. Adding the test data
|
||||||
|
|
||||||
|
Un-flattened device tree structure:
|
||||||
|
|
||||||
|
Un-flattened device tree consists of connected device_node(s) in form of a tree
|
||||||
|
structure described below.
|
||||||
|
|
||||||
|
// following struct members are used to construct the tree
|
||||||
|
struct device_node {
|
||||||
|
...
|
||||||
|
struct device_node *parent;
|
||||||
|
struct device_node *child;
|
||||||
|
struct device_node *sibling;
|
||||||
|
struct device_node *allnext; /* next in list of all nodes */
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
Figure 1, describes a generic structure of machine’s un-flattened device tree
|
||||||
|
considering only child and sibling pointers. There exists another pointer,
|
||||||
|
*parent, that is used to traverse the tree in the reverse direction. So, at
|
||||||
|
a particular level the child node and all the sibling nodes will have a parent
|
||||||
|
pointer pointing to a common node (e.g. child1, sibling2, sibling3, sibling4’s
|
||||||
|
parent points to root node)
|
||||||
|
|
||||||
|
root (‘/’)
|
||||||
|
|
|
||||||
|
child1 -> sibling2 -> sibling3 -> sibling4 -> null
|
||||||
|
| | | |
|
||||||
|
| | | null
|
||||||
|
| | |
|
||||||
|
| | child31 -> sibling32 -> null
|
||||||
|
| | | |
|
||||||
|
| | null null
|
||||||
|
| |
|
||||||
|
| child21 -> sibling22 -> sibling23 -> null
|
||||||
|
| | | |
|
||||||
|
| null null null
|
||||||
|
|
|
||||||
|
child11 -> sibling12 -> sibling13 -> sibling14 -> null
|
||||||
|
| | | |
|
||||||
|
| | | null
|
||||||
|
| | |
|
||||||
|
null null child131 -> null
|
||||||
|
|
|
||||||
|
null
|
||||||
|
|
||||||
|
Figure 1: Generic structure of un-flattened device tree
|
||||||
|
|
||||||
|
|
||||||
|
*allnext: it is used to link all the nodes of DT into a list. So, for the
|
||||||
|
above tree the list would be as follows:
|
||||||
|
|
||||||
|
root->child1->child11->sibling12->sibling13->child131->sibling14->sibling2->
|
||||||
|
child21->sibling22->sibling23->sibling3->child31->sibling32->sibling4->null
|
||||||
|
|
||||||
|
Before executing OF selftest, it is required to attach the test data to
|
||||||
|
machine's device tree (if present). So, when selftest_data_add() is called,
|
||||||
|
at first it reads the flattened device tree data linked into the kernel image
|
||||||
|
via the following kernel symbols:
|
||||||
|
|
||||||
|
__dtb_testcases_begin - address marking the start of test data blob
|
||||||
|
__dtb_testcases_end - address marking the end of test data blob
|
||||||
|
|
||||||
|
Secondly, it calls of_fdt_unflatten_device_tree() to unflatten the flattened
|
||||||
|
blob. And finally, if the machine’s device tree (i.e live tree) is present,
|
||||||
|
then it attaches the unflattened test data tree to the live tree, else it
|
||||||
|
attaches itself as a live device tree.
|
||||||
|
|
||||||
|
attach_node_and_children() uses of_attach_node() to attach the nodes into the
|
||||||
|
live tree as explained below. To explain the same, the test data tree described
|
||||||
|
in Figure 2 is attached to the live tree described in Figure 1.
|
||||||
|
|
||||||
|
root (‘/’)
|
||||||
|
|
|
||||||
|
testcase-data
|
||||||
|
|
|
||||||
|
test-child0 -> test-sibling1 -> test-sibling2 -> test-sibling3 -> null
|
||||||
|
| | | |
|
||||||
|
test-child01 null null null
|
||||||
|
|
||||||
|
|
||||||
|
allnext list:
|
||||||
|
|
||||||
|
root->testcase-data->test-child0->test-child01->test-sibling1->test-sibling2
|
||||||
|
->test-sibling3->null
|
||||||
|
|
||||||
|
Figure 2: Example test data tree to be attached to live tree.
|
||||||
|
|
||||||
|
According to the scenario above, the live tree is already present so it isn’t
|
||||||
|
required to attach the root(‘/’) node. All other nodes are attached by calling
|
||||||
|
of_attach_node() on each node.
|
||||||
|
|
||||||
|
In the function of_attach_node(), the new node is attached as the child of the
|
||||||
|
given parent in live tree. But, if parent already has a child then the new node
|
||||||
|
replaces the current child and turns it into its sibling. So, when the testcase
|
||||||
|
data node is attached to the live tree above (Figure 1), the final structure is
|
||||||
|
as shown in Figure 3.
|
||||||
|
|
||||||
|
root (‘/’)
|
||||||
|
|
|
||||||
|
testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null
|
||||||
|
| | | | |
|
||||||
|
(...) | | | null
|
||||||
|
| | child31 -> sibling32 -> null
|
||||||
|
| | | |
|
||||||
|
| | null null
|
||||||
|
| |
|
||||||
|
| child21 -> sibling22 -> sibling23 -> null
|
||||||
|
| | | |
|
||||||
|
| null null null
|
||||||
|
|
|
||||||
|
child11 -> sibling12 -> sibling13 -> sibling14 -> null
|
||||||
|
| | | |
|
||||||
|
null null | null
|
||||||
|
|
|
||||||
|
child131 -> null
|
||||||
|
|
|
||||||
|
null
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
root (‘/’)
|
||||||
|
|
|
||||||
|
testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null
|
||||||
|
| | | | |
|
||||||
|
| (...) (...) (...) null
|
||||||
|
|
|
||||||
|
test-sibling3 -> test-sibling2 -> test-sibling1 -> test-child0 -> null
|
||||||
|
| | | |
|
||||||
|
null null null test-child01
|
||||||
|
|
||||||
|
|
||||||
|
Figure 3: Live device tree structure after attaching the testcase-data.
|
||||||
|
|
||||||
|
|
||||||
|
Astute readers would have noticed that test-child0 node becomes the last
|
||||||
|
sibling compared to the earlier structure (Figure 2). After attaching first
|
||||||
|
test-child0 the test-sibling1 is attached that pushes the child node
|
||||||
|
(i.e. test-child0) to become a sibling and makes itself a child node,
|
||||||
|
as mentioned above.
|
||||||
|
|
||||||
|
If a duplicate node is found (i.e. if a node with same full_name property is
|
||||||
|
already present in the live tree), then the node isn’t attached rather its
|
||||||
|
properties are updated to the live tree’s node by calling the function
|
||||||
|
update_node_properties().
|
||||||
|
|
||||||
|
|
||||||
|
2.2. Removing the test data
|
||||||
|
|
||||||
|
Once the test case execution is complete, selftest_data_remove is called in
|
||||||
|
order to remove the device nodes attached initially (first the leaf nodes are
|
||||||
|
detached and then moving up the parent nodes are removed, and eventually the
|
||||||
|
whole tree). selftest_data_remove() calls detach_node_and_children() that uses
|
||||||
|
of_detach_node() to detach the nodes from the live device tree.
|
||||||
|
|
||||||
|
To detach a node, of_detach_node() first updates all_next linked list, by
|
||||||
|
attaching the previous node’s allnext to current node’s allnext pointer. And
|
||||||
|
then, it either updates the child pointer of given node’s parent to its
|
||||||
|
sibling or attaches the previous sibling to the given node’s sibling, as
|
||||||
|
appropriate. That is it :)
|
|
@ -2098,7 +2098,7 @@ S: Supported
|
||||||
F: drivers/scsi/bfa/
|
F: drivers/scsi/bfa/
|
||||||
|
|
||||||
BROCADE BNA 10 GIGABIT ETHERNET DRIVER
|
BROCADE BNA 10 GIGABIT ETHERNET DRIVER
|
||||||
M: Rasesh Mody <rmody@brocade.com>
|
M: Rasesh Mody <rasesh.mody@qlogic.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/ethernet/brocade/bna/
|
F: drivers/net/ethernet/brocade/bna/
|
||||||
|
@ -3012,9 +3012,8 @@ S: Supported
|
||||||
F: drivers/acpi/dock.c
|
F: drivers/acpi/dock.c
|
||||||
|
|
||||||
DOCUMENTATION
|
DOCUMENTATION
|
||||||
M: Randy Dunlap <rdunlap@infradead.org>
|
M: Jiri Kosina <jkosina@suse.cz>
|
||||||
L: linux-doc@vger.kernel.org
|
L: linux-doc@vger.kernel.org
|
||||||
T: quilt http://www.infradead.org/~rdunlap/Doc/patches/
|
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/
|
F: Documentation/
|
||||||
X: Documentation/ABI/
|
X: Documentation/ABI/
|
||||||
|
@ -4477,7 +4476,6 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||||
L: linux-i2c@vger.kernel.org
|
L: linux-i2c@vger.kernel.org
|
||||||
L: linux-acpi@vger.kernel.org
|
L: linux-acpi@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/i2c/i2c-acpi.c
|
|
||||||
|
|
||||||
I2C-TAOS-EVM DRIVER
|
I2C-TAOS-EVM DRIVER
|
||||||
M: Jean Delvare <jdelvare@suse.de>
|
M: Jean Delvare <jdelvare@suse.de>
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 3
|
VERSION = 3
|
||||||
PATCHLEVEL = 17
|
PATCHLEVEL = 17
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc6
|
EXTRAVERSION = -rc7
|
||||||
NAME = Shuffling Zombie Juror
|
NAME = Shuffling Zombie Juror
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
@ -447,22 +447,19 @@
|
||||||
gpmc,device-width = <2>;
|
gpmc,device-width = <2>;
|
||||||
gpmc,sync-clk-ps = <0>;
|
gpmc,sync-clk-ps = <0>;
|
||||||
gpmc,cs-on-ns = <0>;
|
gpmc,cs-on-ns = <0>;
|
||||||
gpmc,cs-rd-off-ns = <40>;
|
gpmc,cs-rd-off-ns = <80>;
|
||||||
gpmc,cs-wr-off-ns = <40>;
|
gpmc,cs-wr-off-ns = <80>;
|
||||||
gpmc,adv-on-ns = <0>;
|
gpmc,adv-on-ns = <0>;
|
||||||
gpmc,adv-rd-off-ns = <30>;
|
gpmc,adv-rd-off-ns = <60>;
|
||||||
gpmc,adv-wr-off-ns = <30>;
|
gpmc,adv-wr-off-ns = <60>;
|
||||||
gpmc,we-on-ns = <5>;
|
gpmc,we-on-ns = <10>;
|
||||||
gpmc,we-off-ns = <25>;
|
gpmc,we-off-ns = <50>;
|
||||||
gpmc,oe-on-ns = <2>;
|
gpmc,oe-on-ns = <4>;
|
||||||
gpmc,oe-off-ns = <20>;
|
gpmc,oe-off-ns = <40>;
|
||||||
gpmc,access-ns = <20>;
|
gpmc,access-ns = <40>;
|
||||||
gpmc,wr-access-ns = <40>;
|
gpmc,wr-access-ns = <80>;
|
||||||
gpmc,rd-cycle-ns = <40>;
|
gpmc,rd-cycle-ns = <80>;
|
||||||
gpmc,wr-cycle-ns = <40>;
|
gpmc,wr-cycle-ns = <80>;
|
||||||
gpmc,wait-pin = <0>;
|
|
||||||
gpmc,wait-on-read;
|
|
||||||
gpmc,wait-on-write;
|
|
||||||
gpmc,bus-turnaround-ns = <0>;
|
gpmc,bus-turnaround-ns = <0>;
|
||||||
gpmc,cycle2cycle-delay-ns = <0>;
|
gpmc,cycle2cycle-delay-ns = <0>;
|
||||||
gpmc,clk-activation-ns = <0>;
|
gpmc,clk-activation-ns = <0>;
|
||||||
|
|
|
@ -423,10 +423,14 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
lvds-channel@0 {
|
lvds-channel@0 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
port {
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
lvds0_in: endpoint {
|
lvds0_in: endpoint {
|
||||||
remote-endpoint = <&ipu_di0_lvds0>;
|
remote-endpoint = <&ipu_di0_lvds0>;
|
||||||
};
|
};
|
||||||
|
@ -434,10 +438,14 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
lvds-channel@1 {
|
lvds-channel@1 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
|
||||||
port {
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
|
||||||
lvds1_in: endpoint {
|
lvds1_in: endpoint {
|
||||||
remote-endpoint = <&ipu_di1_lvds1>;
|
remote-endpoint = <&ipu_di1_lvds1>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,7 @@ clocks {
|
||||||
#clock-cells = <0>;
|
#clock-cells = <0>;
|
||||||
compatible = "ti,keystone,psc-clock";
|
compatible = "ti,keystone,psc-clock";
|
||||||
clocks = <&chipclk16>;
|
clocks = <&chipclk16>;
|
||||||
clock-output-names = "usb";
|
clock-output-names = "usb1";
|
||||||
reg = <0x02350004 0xb00>, <0x02350000 0x400>;
|
reg = <0x02350004 0xb00>, <0x02350000 0x400>;
|
||||||
reg-names = "control", "domain";
|
reg-names = "control", "domain";
|
||||||
domain-id = <0>;
|
domain-id = <0>;
|
||||||
|
@ -60,8 +60,8 @@ clocks {
|
||||||
#clock-cells = <0>;
|
#clock-cells = <0>;
|
||||||
compatible = "ti,keystone,psc-clock";
|
compatible = "ti,keystone,psc-clock";
|
||||||
clocks = <&chipclk12>;
|
clocks = <&chipclk12>;
|
||||||
clock-output-names = "pcie";
|
clock-output-names = "pcie1";
|
||||||
reg = <0x0235006c 0xb00>, <0x02350000 0x400>;
|
reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
|
||||||
reg-names = "control", "domain";
|
reg-names = "control", "domain";
|
||||||
domain-id = <18>;
|
domain-id = <18>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -353,13 +353,12 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
ldo8_reg: ldo8 {
|
ldo8_reg: ldo8 {
|
||||||
/* VDD_3v0: Does not go anywhere */
|
/* VDD_3V_GP: act led/serial console */
|
||||||
regulator-name = "ldo8";
|
regulator-name = "ldo8";
|
||||||
regulator-min-microvolt = <3000000>;
|
regulator-min-microvolt = <3000000>;
|
||||||
regulator-max-microvolt = <3000000>;
|
regulator-max-microvolt = <3000000>;
|
||||||
|
regulator-always-on;
|
||||||
regulator-boot-on;
|
regulator-boot-on;
|
||||||
/* Unused */
|
|
||||||
status = "disabled";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ldo9_reg: ldo9 {
|
ldo9_reg: ldo9 {
|
||||||
|
|
|
@ -466,6 +466,7 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)
|
||||||
*/
|
*/
|
||||||
#define v7_exit_coherency_flush(level) \
|
#define v7_exit_coherency_flush(level) \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
|
".arch armv7-a \n\t" \
|
||||||
"stmfd sp!, {fp, ip} \n\t" \
|
"stmfd sp!, {fp, ip} \n\t" \
|
||||||
"mrc p15, 0, r0, c1, c0, 0 @ get SCTLR \n\t" \
|
"mrc p15, 0, r0, c1, c0, 0 @ get SCTLR \n\t" \
|
||||||
"bic r0, r0, #"__stringify(CR_C)" \n\t" \
|
"bic r0, r0, #"__stringify(CR_C)" \n\t" \
|
||||||
|
|
|
@ -81,6 +81,7 @@ static inline void set_tls(unsigned long val)
|
||||||
asm("mcr p15, 0, %0, c13, c0, 3"
|
asm("mcr p15, 0, %0, c13, c0, 3"
|
||||||
: : "r" (val));
|
: : "r" (val));
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef CONFIG_KUSER_HELPERS
|
||||||
/*
|
/*
|
||||||
* User space must never try to access this
|
* User space must never try to access this
|
||||||
* directly. Expect your app to break
|
* directly. Expect your app to break
|
||||||
|
@ -89,6 +90,7 @@ static inline void set_tls(unsigned long val)
|
||||||
* entry-armv.S for details)
|
* entry-armv.S for details)
|
||||||
*/
|
*/
|
||||||
*((unsigned int *)0xffff0ff0) = val;
|
*((unsigned int *)0xffff0ff0) = val;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,10 +110,13 @@
|
||||||
*
|
*
|
||||||
* @ TESTCASE_START
|
* @ TESTCASE_START
|
||||||
* bl __kprobes_test_case_start
|
* bl __kprobes_test_case_start
|
||||||
* @ start of inline data...
|
* .pushsection .rodata
|
||||||
|
* "10:
|
||||||
* .ascii "mov r0, r7" @ text title for test case
|
* .ascii "mov r0, r7" @ text title for test case
|
||||||
* .byte 0
|
* .byte 0
|
||||||
* .align 2, 0
|
* .popsection
|
||||||
|
* @ start of inline data...
|
||||||
|
* .word 10b @ pointer to title in .rodata section
|
||||||
*
|
*
|
||||||
* @ TEST_ARG_REG
|
* @ TEST_ARG_REG
|
||||||
* .byte ARG_TYPE_REG
|
* .byte ARG_TYPE_REG
|
||||||
|
@ -971,7 +974,7 @@ void __naked __kprobes_test_case_start(void)
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"stmdb sp!, {r4-r11} \n\t"
|
"stmdb sp!, {r4-r11} \n\t"
|
||||||
"sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
|
"sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"
|
||||||
"bic r0, lr, #1 @ r0 = inline title string \n\t"
|
"bic r0, lr, #1 @ r0 = inline data \n\t"
|
||||||
"mov r1, sp \n\t"
|
"mov r1, sp \n\t"
|
||||||
"bl kprobes_test_case_start \n\t"
|
"bl kprobes_test_case_start \n\t"
|
||||||
"bx r0 \n\t"
|
"bx r0 \n\t"
|
||||||
|
@ -1349,15 +1352,14 @@ static unsigned long next_instruction(unsigned long pc)
|
||||||
return pc + 4;
|
return pc + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)
|
static uintptr_t __used kprobes_test_case_start(const char **title, void *stack)
|
||||||
{
|
{
|
||||||
struct test_arg *args;
|
struct test_arg *args;
|
||||||
struct test_arg_end *end_arg;
|
struct test_arg_end *end_arg;
|
||||||
unsigned long test_code;
|
unsigned long test_code;
|
||||||
|
|
||||||
args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);
|
current_title = *title++;
|
||||||
|
args = (struct test_arg *)title;
|
||||||
current_title = title;
|
|
||||||
current_args = args;
|
current_args = args;
|
||||||
current_stack = stack;
|
current_stack = stack;
|
||||||
|
|
||||||
|
|
|
@ -111,11 +111,14 @@ struct test_arg_end {
|
||||||
#define TESTCASE_START(title) \
|
#define TESTCASE_START(title) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"bl __kprobes_test_case_start \n\t" \
|
"bl __kprobes_test_case_start \n\t" \
|
||||||
|
".pushsection .rodata \n\t" \
|
||||||
|
"10: \n\t" \
|
||||||
/* don't use .asciz here as 'title' may be */ \
|
/* don't use .asciz here as 'title' may be */ \
|
||||||
/* multiple strings to be concatenated. */ \
|
/* multiple strings to be concatenated. */ \
|
||||||
".ascii "#title" \n\t" \
|
".ascii "#title" \n\t" \
|
||||||
".byte 0 \n\t" \
|
".byte 0 \n\t" \
|
||||||
".align 2, 0 \n\t"
|
".popsection \n\t" \
|
||||||
|
".word 10b \n\t"
|
||||||
|
|
||||||
#define TEST_ARG_REG(reg, val) \
|
#define TEST_ARG_REG(reg, val) \
|
||||||
".byte "__stringify(ARG_TYPE_REG)" \n\t" \
|
".byte "__stringify(ARG_TYPE_REG)" \n\t" \
|
||||||
|
|
|
@ -97,7 +97,7 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)
|
||||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||||
|
|
||||||
if (gate->share_count)
|
if (gate->share_count)
|
||||||
return !!(*gate->share_count);
|
return !!__clk_get_enable_count(hw->clk);
|
||||||
else
|
else
|
||||||
return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
|
return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
|
||||||
}
|
}
|
||||||
|
@ -127,10 +127,6 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
|
||||||
gate->bit_idx = bit_idx;
|
gate->bit_idx = bit_idx;
|
||||||
gate->flags = clk_gate2_flags;
|
gate->flags = clk_gate2_flags;
|
||||||
gate->lock = lock;
|
gate->lock = lock;
|
||||||
|
|
||||||
/* Initialize share_count per hardware state */
|
|
||||||
if (share_count)
|
|
||||||
*share_count = clk_gate2_reg_is_enabled(reg, bit_idx) ? 1 : 0;
|
|
||||||
gate->share_count = share_count;
|
gate->share_count = share_count;
|
||||||
|
|
||||||
init.name = name;
|
init.name = name;
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
menu "TI OMAP/AM/DM/DRA Family"
|
menu "TI OMAP/AM/DM/DRA Family"
|
||||||
depends on ARCH_MULTI_V6 || ARCH_MULTI_V7
|
depends on ARCH_MULTI_V6 || ARCH_MULTI_V7
|
||||||
|
|
||||||
config ARCH_OMAP
|
|
||||||
bool
|
|
||||||
|
|
||||||
config ARCH_OMAP2
|
config ARCH_OMAP2
|
||||||
bool "TI OMAP2"
|
bool "TI OMAP2"
|
||||||
depends on ARCH_MULTI_V6
|
depends on ARCH_MULTI_V6
|
||||||
|
|
|
@ -2065,7 +2065,7 @@ static void _reconfigure_io_chain(void)
|
||||||
|
|
||||||
spin_lock_irqsave(&io_chain_lock, flags);
|
spin_lock_irqsave(&io_chain_lock, flags);
|
||||||
|
|
||||||
if (cpu_is_omap34xx() && omap3_has_io_chain_ctrl())
|
if (cpu_is_omap34xx())
|
||||||
omap3xxx_prm_reconfigure_io_chain();
|
omap3xxx_prm_reconfigure_io_chain();
|
||||||
else if (cpu_is_omap44xx())
|
else if (cpu_is_omap44xx())
|
||||||
omap44xx_prm_reconfigure_io_chain();
|
omap44xx_prm_reconfigure_io_chain();
|
||||||
|
|
|
@ -45,7 +45,7 @@ static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
|
||||||
.ocp_barrier = &omap3xxx_prm_ocp_barrier,
|
.ocp_barrier = &omap3xxx_prm_ocp_barrier,
|
||||||
.save_and_clear_irqen = &omap3xxx_prm_save_and_clear_irqen,
|
.save_and_clear_irqen = &omap3xxx_prm_save_and_clear_irqen,
|
||||||
.restore_irqen = &omap3xxx_prm_restore_irqen,
|
.restore_irqen = &omap3xxx_prm_restore_irqen,
|
||||||
.reconfigure_io_chain = &omap3xxx_prm_reconfigure_io_chain,
|
.reconfigure_io_chain = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -369,15 +369,30 @@ void __init omap3_prm_init_pm(bool has_uart4, bool has_iva)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
|
* omap3430_pre_es3_1_reconfigure_io_chain - restart wake-up daisy chain
|
||||||
|
*
|
||||||
|
* The ST_IO_CHAIN bit does not exist in 3430 before es3.1. The only
|
||||||
|
* thing we can do is toggle EN_IO bit for earlier omaps.
|
||||||
|
*/
|
||||||
|
void omap3430_pre_es3_1_reconfigure_io_chain(void)
|
||||||
|
{
|
||||||
|
omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
|
||||||
|
PM_WKEN);
|
||||||
|
omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
|
||||||
|
PM_WKEN);
|
||||||
|
omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
|
||||||
*
|
*
|
||||||
* Clear any previously-latched I/O wakeup events and ensure that the
|
* Clear any previously-latched I/O wakeup events and ensure that the
|
||||||
* I/O wakeup gates are aligned with the current mux settings. Works
|
* I/O wakeup gates are aligned with the current mux settings. Works
|
||||||
* by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
|
* by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
|
||||||
* deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit. No
|
* deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit. No
|
||||||
* return value.
|
* return value. These registers are only available in 3430 es3.1 and later.
|
||||||
*/
|
*/
|
||||||
void omap3xxx_prm_reconfigure_io_chain(void)
|
void omap3_prm_reconfigure_io_chain(void)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
@ -399,6 +414,15 @@ void omap3xxx_prm_reconfigure_io_chain(void)
|
||||||
omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
|
omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_reconfigure_io_chain - reconfigure I/O chain
|
||||||
|
*/
|
||||||
|
void omap3xxx_prm_reconfigure_io_chain(void)
|
||||||
|
{
|
||||||
|
if (omap3_prcm_irq_setup.reconfigure_io_chain)
|
||||||
|
omap3_prcm_irq_setup.reconfigure_io_chain();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
|
* omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
|
||||||
*
|
*
|
||||||
|
@ -656,6 +680,13 @@ static int omap3xxx_prm_late_init(void)
|
||||||
if (!(prm_features & PRM_HAS_IO_WAKEUP))
|
if (!(prm_features & PRM_HAS_IO_WAKEUP))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (omap3_has_io_chain_ctrl())
|
||||||
|
omap3_prcm_irq_setup.reconfigure_io_chain =
|
||||||
|
omap3_prm_reconfigure_io_chain;
|
||||||
|
else
|
||||||
|
omap3_prcm_irq_setup.reconfigure_io_chain =
|
||||||
|
omap3430_pre_es3_1_reconfigure_io_chain;
|
||||||
|
|
||||||
omap3xxx_prm_enable_io_wakeup();
|
omap3xxx_prm_enable_io_wakeup();
|
||||||
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
|
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
|
@ -61,7 +61,7 @@ EXPORT_SYMBOL(get_clock_tick_rate);
|
||||||
/*
|
/*
|
||||||
* For non device-tree builds, keep legacy timer init
|
* For non device-tree builds, keep legacy timer init
|
||||||
*/
|
*/
|
||||||
void pxa_timer_init(void)
|
void __init pxa_timer_init(void)
|
||||||
{
|
{
|
||||||
pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000),
|
pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000),
|
||||||
get_clock_tick_rate());
|
get_clock_tick_rate());
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
* This code is not portable to processors with late data abort handling.
|
* This code is not portable to processors with late data abort handling.
|
||||||
*/
|
*/
|
||||||
#define CODING_BITS(i) (i & 0x0e000000)
|
#define CODING_BITS(i) (i & 0x0e000000)
|
||||||
|
#define COND_BITS(i) (i & 0xf0000000)
|
||||||
|
|
||||||
#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
|
#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
|
||||||
#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
|
#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
|
||||||
|
@ -821,6 +822,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04000000: /* ldr or str immediate */
|
case 0x04000000: /* ldr or str immediate */
|
||||||
|
if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */
|
||||||
|
goto bad;
|
||||||
offset.un = OFFSET_BITS(instr);
|
offset.un = OFFSET_BITS(instr);
|
||||||
handler = do_alignment_ldrstr;
|
handler = do_alignment_ldrstr;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -157,9 +157,9 @@ ENDPROC(cpu_v7_set_pte_ext)
|
||||||
* TFR EV X F IHD LR S
|
* TFR EV X F IHD LR S
|
||||||
* .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM
|
* .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM
|
||||||
* rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
|
* rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
|
||||||
* 11 0 110 1 0011 1100 .111 1101 < we want
|
* 11 0 110 0 0011 1100 .111 1101 < we want
|
||||||
*/
|
*/
|
||||||
.align 2
|
.align 2
|
||||||
.type v7_crval, #object
|
.type v7_crval, #object
|
||||||
v7_crval:
|
v7_crval:
|
||||||
crval clear=0x0120c302, mmuset=0x30c23c7d, ucset=0x00c01c7c
|
crval clear=0x0122c302, mmuset=0x30c03c7d, ucset=0x00c01c7c
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
config ARCH_OMAP
|
||||||
|
bool
|
||||||
|
|
||||||
if ARCH_OMAP
|
if ARCH_OMAP
|
||||||
|
|
||||||
menu "TI OMAP Common Features"
|
menu "TI OMAP Common Features"
|
||||||
|
|
|
@ -129,7 +129,11 @@ NESTED(_mcount, PT_SIZE, ra)
|
||||||
nop
|
nop
|
||||||
#endif
|
#endif
|
||||||
b ftrace_stub
|
b ftrace_stub
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
|
addiu sp, sp, 8
|
||||||
|
#else
|
||||||
nop
|
nop
|
||||||
|
#endif
|
||||||
|
|
||||||
static_trace:
|
static_trace:
|
||||||
MCOUNT_SAVE_REGS
|
MCOUNT_SAVE_REGS
|
||||||
|
@ -139,6 +143,9 @@ static_trace:
|
||||||
move a1, AT /* arg2: parent's return address */
|
move a1, AT /* arg2: parent's return address */
|
||||||
|
|
||||||
MCOUNT_RESTORE_REGS
|
MCOUNT_RESTORE_REGS
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
|
addiu sp, sp, 8
|
||||||
|
#endif
|
||||||
.globl ftrace_stub
|
.globl ftrace_stub
|
||||||
ftrace_stub:
|
ftrace_stub:
|
||||||
RETURN_BACK
|
RETURN_BACK
|
||||||
|
@ -183,6 +190,11 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
|
||||||
jal prepare_ftrace_return
|
jal prepare_ftrace_return
|
||||||
nop
|
nop
|
||||||
MCOUNT_RESTORE_REGS
|
MCOUNT_RESTORE_REGS
|
||||||
|
#ifndef CONFIG_DYNAMIC_FTRACE
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
|
addiu sp, sp, 8
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
RETURN_BACK
|
RETURN_BACK
|
||||||
END(ftrace_graph_caller)
|
END(ftrace_graph_caller)
|
||||||
|
|
||||||
|
|
|
@ -650,9 +650,9 @@ static inline int cop1_64bit(struct pt_regs *xcp)
|
||||||
#define SIFROMREG(si, x) \
|
#define SIFROMREG(si, x) \
|
||||||
do { \
|
do { \
|
||||||
if (cop1_64bit(xcp)) \
|
if (cop1_64bit(xcp)) \
|
||||||
(si) = get_fpr32(&ctx->fpr[x], 0); \
|
(si) = (int)get_fpr32(&ctx->fpr[x], 0); \
|
||||||
else \
|
else \
|
||||||
(si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \
|
(si) = (int)get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SITOREG(si, x) \
|
#define SITOREG(si, x) \
|
||||||
|
@ -667,7 +667,7 @@ do { \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1))
|
#define SIFROMHREG(si, x) ((si) = (int)get_fpr32(&ctx->fpr[x], 1))
|
||||||
|
|
||||||
#define SITOHREG(si, x) \
|
#define SITOHREG(si, x) \
|
||||||
do { \
|
do { \
|
||||||
|
|
|
@ -33,8 +33,7 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
|
||||||
$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
|
$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
|
||||||
|
|
||||||
ifeq ($(CONFIG_EFI_STUB), y)
|
ifeq ($(CONFIG_EFI_STUB), y)
|
||||||
VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
|
VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
|
||||||
$(objtree)/drivers/firmware/efi/libstub/lib.a
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(obj)/vmlinux: $(VMLINUX_OBJS) FORCE
|
$(obj)/vmlinux: $(VMLINUX_OBJS) FORCE
|
||||||
|
|
|
@ -183,12 +183,27 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
|
||||||
static bool mem_avoid_overlap(struct mem_vector *img)
|
static bool mem_avoid_overlap(struct mem_vector *img)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
struct setup_data *ptr;
|
||||||
|
|
||||||
for (i = 0; i < MEM_AVOID_MAX; i++) {
|
for (i = 0; i < MEM_AVOID_MAX; i++) {
|
||||||
if (mem_overlaps(img, &mem_avoid[i]))
|
if (mem_overlaps(img, &mem_avoid[i]))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Avoid all entries in the setup_data linked list. */
|
||||||
|
ptr = (struct setup_data *)(unsigned long)real_mode->hdr.setup_data;
|
||||||
|
while (ptr) {
|
||||||
|
struct mem_vector avoid;
|
||||||
|
|
||||||
|
avoid.start = (u64)ptr;
|
||||||
|
avoid.size = sizeof(*ptr) + ptr->len;
|
||||||
|
|
||||||
|
if (mem_overlaps(img, &avoid))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ptr = (struct setup_data *)(unsigned long)ptr->next;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,10 @@
|
||||||
|
|
||||||
static efi_system_table_t *sys_table;
|
static efi_system_table_t *sys_table;
|
||||||
|
|
||||||
struct efi_config *efi_early;
|
static struct efi_config *efi_early;
|
||||||
|
|
||||||
|
#define efi_call_early(f, ...) \
|
||||||
|
efi_early->call(efi_early->f, __VA_ARGS__);
|
||||||
|
|
||||||
#define BOOT_SERVICES(bits) \
|
#define BOOT_SERVICES(bits) \
|
||||||
static void setup_boot_services##bits(struct efi_config *c) \
|
static void setup_boot_services##bits(struct efi_config *c) \
|
||||||
|
@ -265,21 +268,25 @@ void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
|
||||||
|
|
||||||
offset = offsetof(typeof(*out), output_string);
|
offset = offsetof(typeof(*out), output_string);
|
||||||
output_string = efi_early->text_output + offset;
|
output_string = efi_early->text_output + offset;
|
||||||
|
out = (typeof(out))(unsigned long)efi_early->text_output;
|
||||||
func = (u64 *)output_string;
|
func = (u64 *)output_string;
|
||||||
|
|
||||||
efi_early->call(*func, efi_early->text_output, str);
|
efi_early->call(*func, out, str);
|
||||||
} else {
|
} else {
|
||||||
struct efi_simple_text_output_protocol_32 *out;
|
struct efi_simple_text_output_protocol_32 *out;
|
||||||
u32 *func;
|
u32 *func;
|
||||||
|
|
||||||
offset = offsetof(typeof(*out), output_string);
|
offset = offsetof(typeof(*out), output_string);
|
||||||
output_string = efi_early->text_output + offset;
|
output_string = efi_early->text_output + offset;
|
||||||
|
out = (typeof(out))(unsigned long)efi_early->text_output;
|
||||||
func = (u32 *)output_string;
|
func = (u32 *)output_string;
|
||||||
|
|
||||||
efi_early->call(*func, efi_early->text_output, str);
|
efi_early->call(*func, out, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "../../../../drivers/firmware/efi/libstub/efi-stub-helper.c"
|
||||||
|
|
||||||
static void find_bits(unsigned long mask, u8 *pos, u8 *size)
|
static void find_bits(unsigned long mask, u8 *pos, u8 *size)
|
||||||
{
|
{
|
||||||
u8 first, len;
|
u8 first, len;
|
||||||
|
@ -360,7 +367,7 @@ free_struct:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t
|
static void
|
||||||
setup_efi_pci32(struct boot_params *params, void **pci_handle,
|
setup_efi_pci32(struct boot_params *params, void **pci_handle,
|
||||||
unsigned long size)
|
unsigned long size)
|
||||||
{
|
{
|
||||||
|
@ -403,8 +410,6 @@ setup_efi_pci32(struct boot_params *params, void **pci_handle,
|
||||||
data = (struct setup_data *)rom;
|
data = (struct setup_data *)rom;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t
|
static efi_status_t
|
||||||
|
@ -463,7 +468,7 @@ free_struct:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t
|
static void
|
||||||
setup_efi_pci64(struct boot_params *params, void **pci_handle,
|
setup_efi_pci64(struct boot_params *params, void **pci_handle,
|
||||||
unsigned long size)
|
unsigned long size)
|
||||||
{
|
{
|
||||||
|
@ -506,11 +511,18 @@ setup_efi_pci64(struct boot_params *params, void **pci_handle,
|
||||||
data = (struct setup_data *)rom;
|
data = (struct setup_data *)rom;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t setup_efi_pci(struct boot_params *params)
|
/*
|
||||||
|
* There's no way to return an informative status from this function,
|
||||||
|
* because any analysis (and printing of error messages) needs to be
|
||||||
|
* done directly at the EFI function call-site.
|
||||||
|
*
|
||||||
|
* For example, EFI_INVALID_PARAMETER could indicate a bug or maybe we
|
||||||
|
* just didn't find any PCI devices, but there's no way to tell outside
|
||||||
|
* the context of the call.
|
||||||
|
*/
|
||||||
|
static void setup_efi_pci(struct boot_params *params)
|
||||||
{
|
{
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
void **pci_handle = NULL;
|
void **pci_handle = NULL;
|
||||||
|
@ -527,7 +539,7 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
|
||||||
size, (void **)&pci_handle);
|
size, (void **)&pci_handle);
|
||||||
|
|
||||||
if (status != EFI_SUCCESS)
|
if (status != EFI_SUCCESS)
|
||||||
return status;
|
return;
|
||||||
|
|
||||||
status = efi_call_early(locate_handle,
|
status = efi_call_early(locate_handle,
|
||||||
EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||||
|
@ -538,13 +550,12 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
|
||||||
goto free_handle;
|
goto free_handle;
|
||||||
|
|
||||||
if (efi_early->is64)
|
if (efi_early->is64)
|
||||||
status = setup_efi_pci64(params, pci_handle, size);
|
setup_efi_pci64(params, pci_handle, size);
|
||||||
else
|
else
|
||||||
status = setup_efi_pci32(params, pci_handle, size);
|
setup_efi_pci32(params, pci_handle, size);
|
||||||
|
|
||||||
free_handle:
|
free_handle:
|
||||||
efi_call_early(free_pool, pci_handle);
|
efi_call_early(free_pool, pci_handle);
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1380,10 +1391,7 @@ struct boot_params *efi_main(struct efi_config *c,
|
||||||
|
|
||||||
setup_graphics(boot_params);
|
setup_graphics(boot_params);
|
||||||
|
|
||||||
status = setup_efi_pci(boot_params);
|
setup_efi_pci(boot_params);
|
||||||
if (status != EFI_SUCCESS) {
|
|
||||||
efi_printk(sys_table, "setup_efi_pci() failed!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
|
status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
|
||||||
sizeof(*gdt), (void **)&gdt);
|
sizeof(*gdt), (void **)&gdt);
|
||||||
|
|
|
@ -103,4 +103,20 @@ struct efi_uga_draw_protocol {
|
||||||
void *blt;
|
void *blt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct efi_config {
|
||||||
|
u64 image_handle;
|
||||||
|
u64 table;
|
||||||
|
u64 allocate_pool;
|
||||||
|
u64 allocate_pages;
|
||||||
|
u64 get_memory_map;
|
||||||
|
u64 free_pool;
|
||||||
|
u64 free_pages;
|
||||||
|
u64 locate_handle;
|
||||||
|
u64 handle_protocol;
|
||||||
|
u64 exit_boot_services;
|
||||||
|
u64 text_output;
|
||||||
|
efi_status_t (*call)(unsigned long, ...);
|
||||||
|
bool is64;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
#endif /* BOOT_COMPRESSED_EBOOT_H */
|
#endif /* BOOT_COMPRESSED_EBOOT_H */
|
||||||
|
|
|
@ -159,30 +159,6 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_EFI_MIXED */
|
#endif /* CONFIG_EFI_MIXED */
|
||||||
|
|
||||||
|
|
||||||
/* arch specific definitions used by the stub code */
|
|
||||||
|
|
||||||
struct efi_config {
|
|
||||||
u64 image_handle;
|
|
||||||
u64 table;
|
|
||||||
u64 allocate_pool;
|
|
||||||
u64 allocate_pages;
|
|
||||||
u64 get_memory_map;
|
|
||||||
u64 free_pool;
|
|
||||||
u64 free_pages;
|
|
||||||
u64 locate_handle;
|
|
||||||
u64 handle_protocol;
|
|
||||||
u64 exit_boot_services;
|
|
||||||
u64 text_output;
|
|
||||||
efi_status_t (*call)(unsigned long, ...);
|
|
||||||
bool is64;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
extern struct efi_config *efi_early;
|
|
||||||
|
|
||||||
#define efi_call_early(f, ...) \
|
|
||||||
efi_early->call(efi_early->f, __VA_ARGS__);
|
|
||||||
|
|
||||||
extern bool efi_reboot_required(void);
|
extern bool efi_reboot_required(void);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -106,14 +106,14 @@ enum fixed_addresses {
|
||||||
__end_of_permanent_fixed_addresses,
|
__end_of_permanent_fixed_addresses,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 256 temporary boot-time mappings, used by early_ioremap(),
|
* 512 temporary boot-time mappings, used by early_ioremap(),
|
||||||
* before ioremap() is functional.
|
* before ioremap() is functional.
|
||||||
*
|
*
|
||||||
* If necessary we round it up to the next 256 pages boundary so
|
* If necessary we round it up to the next 512 pages boundary so
|
||||||
* that we can have a single pgd entry and a single pte table:
|
* that we can have a single pgd entry and a single pte table:
|
||||||
*/
|
*/
|
||||||
#define NR_FIX_BTMAPS 64
|
#define NR_FIX_BTMAPS 64
|
||||||
#define FIX_BTMAPS_SLOTS 4
|
#define FIX_BTMAPS_SLOTS 8
|
||||||
#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
|
#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
|
||||||
FIX_BTMAP_END =
|
FIX_BTMAP_END =
|
||||||
(__end_of_permanent_fixed_addresses ^
|
(__end_of_permanent_fixed_addresses ^
|
||||||
|
|
|
@ -1284,6 +1284,9 @@ static void remove_siblinginfo(int cpu)
|
||||||
|
|
||||||
for_each_cpu(sibling, cpu_sibling_mask(cpu))
|
for_each_cpu(sibling, cpu_sibling_mask(cpu))
|
||||||
cpumask_clear_cpu(cpu, cpu_sibling_mask(sibling));
|
cpumask_clear_cpu(cpu, cpu_sibling_mask(sibling));
|
||||||
|
for_each_cpu(sibling, cpu_llc_shared_mask(cpu))
|
||||||
|
cpumask_clear_cpu(cpu, cpu_llc_shared_mask(sibling));
|
||||||
|
cpumask_clear(cpu_llc_shared_mask(cpu));
|
||||||
cpumask_clear(cpu_sibling_mask(cpu));
|
cpumask_clear(cpu_sibling_mask(cpu));
|
||||||
cpumask_clear(cpu_core_mask(cpu));
|
cpumask_clear(cpu_core_mask(cpu));
|
||||||
c->phys_proc_id = 0;
|
c->phys_proc_id = 0;
|
||||||
|
|
|
@ -419,7 +419,6 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
|
||||||
adev->driver_data = pdata;
|
adev->driver_data = pdata;
|
||||||
pdev = acpi_create_platform_device(adev);
|
pdev = acpi_create_platform_device(adev);
|
||||||
if (!IS_ERR_OR_NULL(pdev)) {
|
if (!IS_ERR_OR_NULL(pdev)) {
|
||||||
device_enable_async_suspend(&pdev->dev);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,7 @@ struct acpi_create_field_info {
|
||||||
u32 field_bit_position;
|
u32 field_bit_position;
|
||||||
u32 field_bit_length;
|
u32 field_bit_length;
|
||||||
u16 resource_length;
|
u16 resource_length;
|
||||||
|
u16 pin_number_index;
|
||||||
u8 field_flags;
|
u8 field_flags;
|
||||||
u8 attribute;
|
u8 attribute;
|
||||||
u8 field_type;
|
u8 field_type;
|
||||||
|
|
|
@ -264,6 +264,7 @@ struct acpi_object_region_field {
|
||||||
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
|
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
|
||||||
union acpi_operand_object *region_obj; /* Containing op_region object */
|
union acpi_operand_object *region_obj; /* Containing op_region object */
|
||||||
u8 *resource_buffer; /* resource_template for serial regions/fields */
|
u8 *resource_buffer; /* resource_template for serial regions/fields */
|
||||||
|
u16 pin_number_index; /* Index relative to previous Connection/Template */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct acpi_object_bank_field {
|
struct acpi_object_bank_field {
|
||||||
|
|
|
@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
|
||||||
*/
|
*/
|
||||||
info->resource_buffer = NULL;
|
info->resource_buffer = NULL;
|
||||||
info->connection_node = NULL;
|
info->connection_node = NULL;
|
||||||
|
info->pin_number_index = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A Connection() is either an actual resource descriptor (buffer)
|
* A Connection() is either an actual resource descriptor (buffer)
|
||||||
|
@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
|
||||||
}
|
}
|
||||||
|
|
||||||
info->field_bit_position += info->field_bit_length;
|
info->field_bit_position += info->field_bit_length;
|
||||||
|
info->pin_number_index++; /* Index relative to previous Connection() */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
||||||
union acpi_operand_object *region_obj2;
|
union acpi_operand_object *region_obj2;
|
||||||
void *region_context = NULL;
|
void *region_context = NULL;
|
||||||
struct acpi_connection_info *context;
|
struct acpi_connection_info *context;
|
||||||
|
acpi_physical_address address;
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
|
ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
|
||||||
|
|
||||||
|
@ -231,25 +232,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
||||||
/* We have everything we need, we can invoke the address space handler */
|
/* We have everything we need, we can invoke the address space handler */
|
||||||
|
|
||||||
handler = handler_desc->address_space.handler;
|
handler = handler_desc->address_space.handler;
|
||||||
|
address = (region_obj->region.address + region_offset);
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
|
|
||||||
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
|
|
||||||
®ion_obj->region.handler->address_space, handler,
|
|
||||||
ACPI_FORMAT_NATIVE_UINT(region_obj->region.address +
|
|
||||||
region_offset),
|
|
||||||
acpi_ut_get_region_name(region_obj->region.
|
|
||||||
space_id)));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special handling for generic_serial_bus and general_purpose_io:
|
* Special handling for generic_serial_bus and general_purpose_io:
|
||||||
* There are three extra parameters that must be passed to the
|
* There are three extra parameters that must be passed to the
|
||||||
* handler via the context:
|
* handler via the context:
|
||||||
* 1) Connection buffer, a resource template from Connection() op.
|
* 1) Connection buffer, a resource template from Connection() op
|
||||||
* 2) Length of the above buffer.
|
* 2) Length of the above buffer
|
||||||
* 3) Actual access length from the access_as() op.
|
* 3) Actual access length from the access_as() op
|
||||||
|
*
|
||||||
|
* In addition, for general_purpose_io, the Address and bit_width fields
|
||||||
|
* are defined as follows:
|
||||||
|
* 1) Address is the pin number index of the field (bit offset from
|
||||||
|
* the previous Connection)
|
||||||
|
* 2) bit_width is the actual bit length of the field (number of pins)
|
||||||
*/
|
*/
|
||||||
if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) ||
|
if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
|
||||||
(region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) &&
|
|
||||||
context && field_obj) {
|
context && field_obj) {
|
||||||
|
|
||||||
/* Get the Connection (resource_template) buffer */
|
/* Get the Connection (resource_template) buffer */
|
||||||
|
@ -258,6 +257,24 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
||||||
context->length = field_obj->field.resource_length;
|
context->length = field_obj->field.resource_length;
|
||||||
context->access_length = field_obj->field.access_length;
|
context->access_length = field_obj->field.access_length;
|
||||||
}
|
}
|
||||||
|
if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
|
||||||
|
context && field_obj) {
|
||||||
|
|
||||||
|
/* Get the Connection (resource_template) buffer */
|
||||||
|
|
||||||
|
context->connection = field_obj->field.resource_buffer;
|
||||||
|
context->length = field_obj->field.resource_length;
|
||||||
|
context->access_length = field_obj->field.access_length;
|
||||||
|
address = field_obj->field.pin_number_index;
|
||||||
|
bit_width = field_obj->field.bit_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
|
||||||
|
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
|
||||||
|
®ion_obj->region.handler->address_space, handler,
|
||||||
|
ACPI_FORMAT_NATIVE_UINT(address),
|
||||||
|
acpi_ut_get_region_name(region_obj->region.
|
||||||
|
space_id)));
|
||||||
|
|
||||||
if (!(handler_desc->address_space.handler_flags &
|
if (!(handler_desc->address_space.handler_flags &
|
||||||
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
|
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
|
||||||
|
@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
||||||
|
|
||||||
/* Call the handler */
|
/* Call the handler */
|
||||||
|
|
||||||
status = handler(function,
|
status = handler(function, address, bit_width, value, context,
|
||||||
(region_obj->region.address + region_offset),
|
|
||||||
bit_width, value, context,
|
|
||||||
region_obj2->extra.region_context);
|
region_obj2->extra.region_context);
|
||||||
|
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
|
|
|
@ -253,6 +253,37 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
|
||||||
buffer = &buffer_desc->integer.value;
|
buffer = &buffer_desc->integer.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||||
|
(obj_desc->field.region_obj->region.space_id ==
|
||||||
|
ACPI_ADR_SPACE_GPIO)) {
|
||||||
|
/*
|
||||||
|
* For GPIO (general_purpose_io), the Address will be the bit offset
|
||||||
|
* from the previous Connection() operator, making it effectively a
|
||||||
|
* pin number index. The bit_length is the length of the field, which
|
||||||
|
* is thus the number of pins.
|
||||||
|
*/
|
||||||
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
|
"GPIO FieldRead [FROM]: Pin %u Bits %u\n",
|
||||||
|
obj_desc->field.pin_number_index,
|
||||||
|
obj_desc->field.bit_length));
|
||||||
|
|
||||||
|
/* Lock entire transaction if requested */
|
||||||
|
|
||||||
|
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
/* Perform the write */
|
||||||
|
|
||||||
|
status = acpi_ex_access_region(obj_desc, 0,
|
||||||
|
(u64 *)buffer, ACPI_READ);
|
||||||
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
acpi_ut_remove_reference(buffer_desc);
|
||||||
|
} else {
|
||||||
|
*ret_buffer_desc = buffer_desc;
|
||||||
|
}
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
|
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
|
||||||
obj_desc, obj_desc->common.type, buffer,
|
obj_desc, obj_desc->common.type, buffer,
|
||||||
|
@ -413,6 +444,42 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
||||||
|
|
||||||
*result_desc = buffer_desc;
|
*result_desc = buffer_desc;
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
|
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||||
|
(obj_desc->field.region_obj->region.space_id ==
|
||||||
|
ACPI_ADR_SPACE_GPIO)) {
|
||||||
|
/*
|
||||||
|
* For GPIO (general_purpose_io), we will bypass the entire field
|
||||||
|
* mechanism and handoff the bit address and bit width directly to
|
||||||
|
* the handler. The Address will be the bit offset
|
||||||
|
* from the previous Connection() operator, making it effectively a
|
||||||
|
* pin number index. The bit_length is the length of the field, which
|
||||||
|
* is thus the number of pins.
|
||||||
|
*/
|
||||||
|
if (source_desc->common.type != ACPI_TYPE_INTEGER) {
|
||||||
|
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
|
"GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
|
||||||
|
acpi_ut_get_type_name(source_desc->common.
|
||||||
|
type),
|
||||||
|
source_desc->common.type,
|
||||||
|
(u32)source_desc->integer.value,
|
||||||
|
obj_desc->field.pin_number_index,
|
||||||
|
obj_desc->field.bit_length));
|
||||||
|
|
||||||
|
buffer = &source_desc->integer.value;
|
||||||
|
|
||||||
|
/* Lock entire transaction if requested */
|
||||||
|
|
||||||
|
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
/* Perform the write */
|
||||||
|
|
||||||
|
status = acpi_ex_access_region(obj_desc, 0,
|
||||||
|
(u64 *)buffer, ACPI_WRITE);
|
||||||
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a pointer to the data to be written */
|
/* Get a pointer to the data to be written */
|
||||||
|
|
|
@ -484,6 +484,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
|
||||||
obj_desc->field.resource_length = info->resource_length;
|
obj_desc->field.resource_length = info->resource_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj_desc->field.pin_number_index = info->pin_number_index;
|
||||||
|
|
||||||
/* Allow full data read from EC address space */
|
/* Allow full data read from EC address space */
|
||||||
|
|
||||||
if ((obj_desc->field.region_obj->region.space_id ==
|
if ((obj_desc->field.region_obj->region.space_id ==
|
||||||
|
|
|
@ -99,6 +99,13 @@ static void container_device_detach(struct acpi_device *adev)
|
||||||
device_unregister(dev);
|
device_unregister(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void container_device_online(struct acpi_device *adev)
|
||||||
|
{
|
||||||
|
struct device *dev = acpi_driver_data(adev);
|
||||||
|
|
||||||
|
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
||||||
|
}
|
||||||
|
|
||||||
static struct acpi_scan_handler container_handler = {
|
static struct acpi_scan_handler container_handler = {
|
||||||
.ids = container_device_ids,
|
.ids = container_device_ids,
|
||||||
.attach = container_device_attach,
|
.attach = container_device_attach,
|
||||||
|
@ -106,6 +113,7 @@ static struct acpi_scan_handler container_handler = {
|
||||||
.hotplug = {
|
.hotplug = {
|
||||||
.enabled = true,
|
.enabled = true,
|
||||||
.demand_offline = true,
|
.demand_offline = true,
|
||||||
|
.notify_online = container_device_online,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||||
list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
|
list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
|
||||||
count = snprintf(&modalias[len], size, "%s:", id->id);
|
count = snprintf(&modalias[len], size, "%s:", id->id);
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
return EINVAL;
|
return -EINVAL;
|
||||||
if (count >= size)
|
if (count >= size)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
len += count;
|
len += count;
|
||||||
|
@ -2189,6 +2189,9 @@ static void acpi_bus_attach(struct acpi_device *device)
|
||||||
ok:
|
ok:
|
||||||
list_for_each_entry(child, &device->children, node)
|
list_for_each_entry(child, &device->children, node)
|
||||||
acpi_bus_attach(child);
|
acpi_bus_attach(child);
|
||||||
|
|
||||||
|
if (device->handler && device->handler->hotplug.notify_online)
|
||||||
|
device->handler->hotplug.notify_online(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -750,6 +750,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
|
||||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
|
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.callback = video_disable_native_backlight,
|
||||||
|
.ident = "ThinkPad X201s",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/* The native backlight controls do not work on some older machines */
|
/* The native backlight controls do not work on some older machines */
|
||||||
{
|
{
|
||||||
|
|
|
@ -188,31 +188,31 @@ static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct l3_masters_data omap_l3_masters[] = {
|
static struct l3_masters_data omap_l3_masters[] = {
|
||||||
{ 0x0 , "MPU"},
|
{ 0x00, "MPU"},
|
||||||
{ 0x10, "CS_ADP"},
|
{ 0x04, "CS_ADP"},
|
||||||
{ 0x14, "xxx"},
|
{ 0x05, "xxx"},
|
||||||
{ 0x20, "DSP"},
|
{ 0x08, "DSP"},
|
||||||
{ 0x30, "IVAHD"},
|
{ 0x0C, "IVAHD"},
|
||||||
{ 0x40, "ISS"},
|
{ 0x10, "ISS"},
|
||||||
{ 0x44, "DucatiM3"},
|
{ 0x11, "DucatiM3"},
|
||||||
{ 0x48, "FaceDetect"},
|
{ 0x12, "FaceDetect"},
|
||||||
{ 0x50, "SDMA_Rd"},
|
{ 0x14, "SDMA_Rd"},
|
||||||
{ 0x54, "SDMA_Wr"},
|
{ 0x15, "SDMA_Wr"},
|
||||||
{ 0x58, "xxx"},
|
{ 0x16, "xxx"},
|
||||||
{ 0x5C, "xxx"},
|
{ 0x17, "xxx"},
|
||||||
{ 0x60, "SGX"},
|
{ 0x18, "SGX"},
|
||||||
{ 0x70, "DSS"},
|
{ 0x1C, "DSS"},
|
||||||
{ 0x80, "C2C"},
|
{ 0x20, "C2C"},
|
||||||
{ 0x88, "xxx"},
|
{ 0x22, "xxx"},
|
||||||
{ 0x8C, "xxx"},
|
{ 0x23, "xxx"},
|
||||||
{ 0x90, "HSI"},
|
{ 0x24, "HSI"},
|
||||||
{ 0xA0, "MMC1"},
|
{ 0x28, "MMC1"},
|
||||||
{ 0xA4, "MMC2"},
|
{ 0x29, "MMC2"},
|
||||||
{ 0xA8, "MMC6"},
|
{ 0x2A, "MMC6"},
|
||||||
{ 0xB0, "UNIPRO1"},
|
{ 0x2C, "UNIPRO1"},
|
||||||
{ 0xC0, "USBHOSTHS"},
|
{ 0x30, "USBHOSTHS"},
|
||||||
{ 0xC4, "USBOTGHS"},
|
{ 0x31, "USBOTGHS"},
|
||||||
{ 0xC8, "USBHOSTFS"}
|
{ 0x32, "USBHOSTFS"}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct l3_flagmux_data *omap_l3_flagmux[] = {
|
static struct l3_flagmux_data *omap_l3_flagmux[] = {
|
||||||
|
|
|
@ -1289,6 +1289,8 @@ err_get_freq:
|
||||||
per_cpu(cpufreq_cpu_data, j) = NULL;
|
per_cpu(cpufreq_cpu_data, j) = NULL;
|
||||||
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
|
|
||||||
|
up_write(&policy->rwsem);
|
||||||
|
|
||||||
if (cpufreq_driver->exit)
|
if (cpufreq_driver->exit)
|
||||||
cpufreq_driver->exit(policy);
|
cpufreq_driver->exit(policy);
|
||||||
err_set_policy_cpu:
|
err_set_policy_cpu:
|
||||||
|
@ -1656,6 +1658,8 @@ void cpufreq_suspend(void)
|
||||||
if (!cpufreq_driver)
|
if (!cpufreq_driver)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
cpufreq_suspended = true;
|
||||||
|
|
||||||
if (!has_target())
|
if (!has_target())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1670,8 +1674,6 @@ void cpufreq_suspend(void)
|
||||||
pr_err("%s: Failed to suspend driver: %p\n", __func__,
|
pr_err("%s: Failed to suspend driver: %p\n", __func__,
|
||||||
policy);
|
policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpufreq_suspended = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1687,13 +1689,13 @@ void cpufreq_resume(void)
|
||||||
if (!cpufreq_driver)
|
if (!cpufreq_driver)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
cpufreq_suspended = false;
|
||||||
|
|
||||||
if (!has_target())
|
if (!has_target())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pr_debug("%s: Resuming Governors\n", __func__);
|
pr_debug("%s: Resuming Governors\n", __func__);
|
||||||
|
|
||||||
cpufreq_suspended = false;
|
|
||||||
|
|
||||||
list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
|
list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
|
||||||
if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
|
if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
|
||||||
pr_err("%s: Failed to resume driver: %p\n", __func__,
|
pr_err("%s: Failed to resume driver: %p\n", __func__,
|
||||||
|
|
|
@ -1017,6 +1017,11 @@ static int omap_dma_resume(struct omap_chan *c)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (c->paused) {
|
if (c->paused) {
|
||||||
|
mb();
|
||||||
|
|
||||||
|
/* Restore channel link register */
|
||||||
|
omap_dma_chan_write(c, CLNK_CTRL, c->desc->clnk_ctrl);
|
||||||
|
|
||||||
omap_dma_start(c, c->desc);
|
omap_dma_start(c, c->desc);
|
||||||
c->paused = false;
|
c->paused = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,4 @@ obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
|
||||||
obj-$(CONFIG_UEFI_CPER) += cper.o
|
obj-$(CONFIG_UEFI_CPER) += cper.o
|
||||||
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
|
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
|
||||||
obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
|
obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
|
||||||
obj-$(CONFIG_EFI_STUB) += libstub/
|
obj-$(CONFIG_EFI_ARM_STUB) += libstub/
|
||||||
|
|
|
@ -377,8 +377,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
|
||||||
struct gpio_chip *chip = achip->chip;
|
struct gpio_chip *chip = achip->chip;
|
||||||
struct acpi_resource_gpio *agpio;
|
struct acpi_resource_gpio *agpio;
|
||||||
struct acpi_resource *ares;
|
struct acpi_resource *ares;
|
||||||
|
int pin_index = (int)address;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
bool pull_up;
|
bool pull_up;
|
||||||
|
int length;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
status = acpi_buffer_to_resource(achip->conn_info.connection,
|
status = acpi_buffer_to_resource(achip->conn_info.connection,
|
||||||
|
@ -400,7 +402,8 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
|
||||||
return AE_BAD_PARAMETER;
|
return AE_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < agpio->pin_table_length; i++) {
|
length = min(agpio->pin_table_length, (u16)(pin_index + bits));
|
||||||
|
for (i = pin_index; i < length; ++i) {
|
||||||
unsigned pin = agpio->pin_table[i];
|
unsigned pin = agpio->pin_table[i];
|
||||||
struct acpi_gpio_connection *conn;
|
struct acpi_gpio_connection *conn;
|
||||||
struct gpio_desc *desc;
|
struct gpio_desc *desc;
|
||||||
|
|
|
@ -413,12 +413,12 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_set_chained_handler(parent_irq, parent_handler);
|
|
||||||
/*
|
/*
|
||||||
* The parent irqchip is already using the chip_data for this
|
* The parent irqchip is already using the chip_data for this
|
||||||
* irqchip, so our callbacks simply use the handler_data.
|
* irqchip, so our callbacks simply use the handler_data.
|
||||||
*/
|
*/
|
||||||
irq_set_handler_data(parent_irq, gpiochip);
|
irq_set_handler_data(parent_irq, gpiochip);
|
||||||
|
irq_set_chained_handler(parent_irq, parent_handler);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
|
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
|
||||||
|
|
||||||
|
@ -1674,7 +1674,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
|
||||||
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
|
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
|
||||||
|
|
||||||
/* No particular flag request, return here... */
|
/* No particular flag request, return here... */
|
||||||
if (flags & GPIOD_FLAGS_BIT_DIR_SET)
|
if (!(flags & GPIOD_FLAGS_BIT_DIR_SET))
|
||||||
return desc;
|
return desc;
|
||||||
|
|
||||||
/* Process flags */
|
/* Process flags */
|
||||||
|
|
|
@ -709,11 +709,13 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring)
|
||||||
BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count));
|
BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count));
|
||||||
BUG_ON(!validate_regs_sorted(ring));
|
BUG_ON(!validate_regs_sorted(ring));
|
||||||
|
|
||||||
ret = init_hash_table(ring, cmd_tables, cmd_table_count);
|
if (hash_empty(ring->cmd_hash)) {
|
||||||
if (ret) {
|
ret = init_hash_table(ring, cmd_tables, cmd_table_count);
|
||||||
DRM_ERROR("CMD: cmd_parser_init failed!\n");
|
if (ret) {
|
||||||
fini_hash_table(ring);
|
DRM_ERROR("CMD: cmd_parser_init failed!\n");
|
||||||
return ret;
|
fini_hash_table(ring);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ring->needs_cmd_parser = true;
|
ring->needs_cmd_parser = true;
|
||||||
|
|
|
@ -732,7 +732,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
||||||
if (tmp & HDMI_MODE_SELECT_HDMI)
|
if (tmp & HDMI_MODE_SELECT_HDMI)
|
||||||
pipe_config->has_hdmi_sink = true;
|
pipe_config->has_hdmi_sink = true;
|
||||||
|
|
||||||
if (tmp & HDMI_MODE_SELECT_HDMI)
|
if (tmp & SDVO_AUDIO_ENABLE)
|
||||||
pipe_config->has_audio = true;
|
pipe_config->has_audio = true;
|
||||||
|
|
||||||
if (!HAS_PCH_SPLIT(dev) &&
|
if (!HAS_PCH_SPLIT(dev) &&
|
||||||
|
|
|
@ -4803,7 +4803,7 @@ struct bonaire_mqd
|
||||||
*/
|
*/
|
||||||
static int cik_cp_compute_resume(struct radeon_device *rdev)
|
static int cik_cp_compute_resume(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
int r, i, idx;
|
int r, i, j, idx;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
bool use_doorbell = true;
|
bool use_doorbell = true;
|
||||||
u64 hqd_gpu_addr;
|
u64 hqd_gpu_addr;
|
||||||
|
@ -4922,7 +4922,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
|
||||||
mqd->queue_state.cp_hqd_pq_wptr= 0;
|
mqd->queue_state.cp_hqd_pq_wptr= 0;
|
||||||
if (RREG32(CP_HQD_ACTIVE) & 1) {
|
if (RREG32(CP_HQD_ACTIVE) & 1) {
|
||||||
WREG32(CP_HQD_DEQUEUE_REQUEST, 1);
|
WREG32(CP_HQD_DEQUEUE_REQUEST, 1);
|
||||||
for (i = 0; i < rdev->usec_timeout; i++) {
|
for (j = 0; j < rdev->usec_timeout; j++) {
|
||||||
if (!(RREG32(CP_HQD_ACTIVE) & 1))
|
if (!(RREG32(CP_HQD_ACTIVE) & 1))
|
||||||
break;
|
break;
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
@ -7751,17 +7751,17 @@ static inline u32 cik_get_ih_wptr(struct radeon_device *rdev)
|
||||||
wptr = RREG32(IH_RB_WPTR);
|
wptr = RREG32(IH_RB_WPTR);
|
||||||
|
|
||||||
if (wptr & RB_OVERFLOW) {
|
if (wptr & RB_OVERFLOW) {
|
||||||
|
wptr &= ~RB_OVERFLOW;
|
||||||
/* When a ring buffer overflow happen start parsing interrupt
|
/* When a ring buffer overflow happen start parsing interrupt
|
||||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||||
* this should allow us to catchup.
|
* this should allow us to catchup.
|
||||||
*/
|
*/
|
||||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
|
||||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||||
tmp = RREG32(IH_RB_CNTL);
|
tmp = RREG32(IH_RB_CNTL);
|
||||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||||
WREG32(IH_RB_CNTL, tmp);
|
WREG32(IH_RB_CNTL, tmp);
|
||||||
wptr &= ~RB_OVERFLOW;
|
|
||||||
}
|
}
|
||||||
return (wptr & rdev->ih.ptr_mask);
|
return (wptr & rdev->ih.ptr_mask);
|
||||||
}
|
}
|
||||||
|
@ -8251,6 +8251,7 @@ restart_ih:
|
||||||
/* wptr/rptr are in bytes! */
|
/* wptr/rptr are in bytes! */
|
||||||
rptr += 16;
|
rptr += 16;
|
||||||
rptr &= rdev->ih.ptr_mask;
|
rptr &= rdev->ih.ptr_mask;
|
||||||
|
WREG32(IH_RB_RPTR, rptr);
|
||||||
}
|
}
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
schedule_work(&rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
|
@ -8259,7 +8260,6 @@ restart_ih:
|
||||||
if (queue_thermal)
|
if (queue_thermal)
|
||||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||||
rdev->ih.rptr = rptr;
|
rdev->ih.rptr = rptr;
|
||||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
|
||||||
atomic_set(&rdev->ih.lock, 0);
|
atomic_set(&rdev->ih.lock, 0);
|
||||||
|
|
||||||
/* make sure wptr hasn't changed while processing */
|
/* make sure wptr hasn't changed while processing */
|
||||||
|
|
|
@ -4749,17 +4749,17 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
|
||||||
wptr = RREG32(IH_RB_WPTR);
|
wptr = RREG32(IH_RB_WPTR);
|
||||||
|
|
||||||
if (wptr & RB_OVERFLOW) {
|
if (wptr & RB_OVERFLOW) {
|
||||||
|
wptr &= ~RB_OVERFLOW;
|
||||||
/* When a ring buffer overflow happen start parsing interrupt
|
/* When a ring buffer overflow happen start parsing interrupt
|
||||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||||
* this should allow us to catchup.
|
* this should allow us to catchup.
|
||||||
*/
|
*/
|
||||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
|
||||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||||
tmp = RREG32(IH_RB_CNTL);
|
tmp = RREG32(IH_RB_CNTL);
|
||||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||||
WREG32(IH_RB_CNTL, tmp);
|
WREG32(IH_RB_CNTL, tmp);
|
||||||
wptr &= ~RB_OVERFLOW;
|
|
||||||
}
|
}
|
||||||
return (wptr & rdev->ih.ptr_mask);
|
return (wptr & rdev->ih.ptr_mask);
|
||||||
}
|
}
|
||||||
|
@ -5137,6 +5137,7 @@ restart_ih:
|
||||||
/* wptr/rptr are in bytes! */
|
/* wptr/rptr are in bytes! */
|
||||||
rptr += 16;
|
rptr += 16;
|
||||||
rptr &= rdev->ih.ptr_mask;
|
rptr &= rdev->ih.ptr_mask;
|
||||||
|
WREG32(IH_RB_RPTR, rptr);
|
||||||
}
|
}
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
schedule_work(&rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
|
@ -5145,7 +5146,6 @@ restart_ih:
|
||||||
if (queue_thermal && rdev->pm.dpm_enabled)
|
if (queue_thermal && rdev->pm.dpm_enabled)
|
||||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||||
rdev->ih.rptr = rptr;
|
rdev->ih.rptr = rptr;
|
||||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
|
||||||
atomic_set(&rdev->ih.lock, 0);
|
atomic_set(&rdev->ih.lock, 0);
|
||||||
|
|
||||||
/* make sure wptr hasn't changed while processing */
|
/* make sure wptr hasn't changed while processing */
|
||||||
|
|
|
@ -3792,17 +3792,17 @@ static u32 r600_get_ih_wptr(struct radeon_device *rdev)
|
||||||
wptr = RREG32(IH_RB_WPTR);
|
wptr = RREG32(IH_RB_WPTR);
|
||||||
|
|
||||||
if (wptr & RB_OVERFLOW) {
|
if (wptr & RB_OVERFLOW) {
|
||||||
|
wptr &= ~RB_OVERFLOW;
|
||||||
/* When a ring buffer overflow happen start parsing interrupt
|
/* When a ring buffer overflow happen start parsing interrupt
|
||||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||||
* this should allow us to catchup.
|
* this should allow us to catchup.
|
||||||
*/
|
*/
|
||||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
|
||||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||||
tmp = RREG32(IH_RB_CNTL);
|
tmp = RREG32(IH_RB_CNTL);
|
||||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||||
WREG32(IH_RB_CNTL, tmp);
|
WREG32(IH_RB_CNTL, tmp);
|
||||||
wptr &= ~RB_OVERFLOW;
|
|
||||||
}
|
}
|
||||||
return (wptr & rdev->ih.ptr_mask);
|
return (wptr & rdev->ih.ptr_mask);
|
||||||
}
|
}
|
||||||
|
@ -4048,6 +4048,7 @@ restart_ih:
|
||||||
/* wptr/rptr are in bytes! */
|
/* wptr/rptr are in bytes! */
|
||||||
rptr += 16;
|
rptr += 16;
|
||||||
rptr &= rdev->ih.ptr_mask;
|
rptr &= rdev->ih.ptr_mask;
|
||||||
|
WREG32(IH_RB_RPTR, rptr);
|
||||||
}
|
}
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
schedule_work(&rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
|
@ -4056,7 +4057,6 @@ restart_ih:
|
||||||
if (queue_thermal && rdev->pm.dpm_enabled)
|
if (queue_thermal && rdev->pm.dpm_enabled)
|
||||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||||
rdev->ih.rptr = rptr;
|
rdev->ih.rptr = rptr;
|
||||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
|
||||||
atomic_set(&rdev->ih.lock, 0);
|
atomic_set(&rdev->ih.lock, 0);
|
||||||
|
|
||||||
/* make sure wptr hasn't changed while processing */
|
/* make sure wptr hasn't changed while processing */
|
||||||
|
|
|
@ -106,6 +106,7 @@ extern int radeon_vm_block_size;
|
||||||
extern int radeon_deep_color;
|
extern int radeon_deep_color;
|
||||||
extern int radeon_use_pflipirq;
|
extern int radeon_use_pflipirq;
|
||||||
extern int radeon_bapm;
|
extern int radeon_bapm;
|
||||||
|
extern int radeon_backlight;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy from radeon_drv.h so we don't have to include both and have conflicting
|
* Copy from radeon_drv.h so we don't have to include both and have conflicting
|
||||||
|
|
|
@ -123,6 +123,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {
|
||||||
* https://bugzilla.kernel.org/show_bug.cgi?id=51381
|
* https://bugzilla.kernel.org/show_bug.cgi?id=51381
|
||||||
*/
|
*/
|
||||||
{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x108c, RADEON_PX_QUIRK_DISABLE_PX },
|
{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x108c, RADEON_PX_QUIRK_DISABLE_PX },
|
||||||
|
/* Asus K53TK laptop with AMD A6-3420M APU and Radeon 7670m GPU
|
||||||
|
* https://bugzilla.kernel.org/show_bug.cgi?id=51381
|
||||||
|
*/
|
||||||
|
{ PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
|
||||||
/* macbook pro 8.2 */
|
/* macbook pro 8.2 */
|
||||||
{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
|
{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 0, 0, 0, 0, 0 },
|
||||||
|
|
|
@ -181,6 +181,7 @@ int radeon_vm_block_size = -1;
|
||||||
int radeon_deep_color = 0;
|
int radeon_deep_color = 0;
|
||||||
int radeon_use_pflipirq = 2;
|
int radeon_use_pflipirq = 2;
|
||||||
int radeon_bapm = -1;
|
int radeon_bapm = -1;
|
||||||
|
int radeon_backlight = -1;
|
||||||
|
|
||||||
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
|
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
|
||||||
module_param_named(no_wb, radeon_no_wb, int, 0444);
|
module_param_named(no_wb, radeon_no_wb, int, 0444);
|
||||||
|
@ -263,6 +264,9 @@ module_param_named(use_pflipirq, radeon_use_pflipirq, int, 0444);
|
||||||
MODULE_PARM_DESC(bapm, "BAPM support (1 = enable, 0 = disable, -1 = auto)");
|
MODULE_PARM_DESC(bapm, "BAPM support (1 = enable, 0 = disable, -1 = auto)");
|
||||||
module_param_named(bapm, radeon_bapm, int, 0444);
|
module_param_named(bapm, radeon_bapm, int, 0444);
|
||||||
|
|
||||||
|
MODULE_PARM_DESC(backlight, "backlight support (1 = enable, 0 = disable, -1 = auto)");
|
||||||
|
module_param_named(backlight, radeon_backlight, int, 0444);
|
||||||
|
|
||||||
static struct pci_device_id pciidlist[] = {
|
static struct pci_device_id pciidlist[] = {
|
||||||
radeon_PCI_IDS
|
radeon_PCI_IDS
|
||||||
};
|
};
|
||||||
|
|
|
@ -158,10 +158,43 @@ radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
|
||||||
|
struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = radeon_encoder->base.dev;
|
||||||
|
struct radeon_device *rdev = dev->dev_private;
|
||||||
|
bool use_bl = false;
|
||||||
|
|
||||||
|
if (!(radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (radeon_backlight == 0) {
|
||||||
|
return;
|
||||||
|
} else if (radeon_backlight == 1) {
|
||||||
|
use_bl = true;
|
||||||
|
} else if (radeon_backlight == -1) {
|
||||||
|
/* Quirks */
|
||||||
|
/* Amilo Xi 2550 only works with acpi bl */
|
||||||
|
if ((rdev->pdev->device == 0x9583) &&
|
||||||
|
(rdev->pdev->subsystem_vendor == 0x1734) &&
|
||||||
|
(rdev->pdev->subsystem_device == 0x1107))
|
||||||
|
use_bl = false;
|
||||||
|
else
|
||||||
|
use_bl = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_bl) {
|
||||||
|
if (rdev->is_atom_bios)
|
||||||
|
radeon_atom_backlight_init(radeon_encoder, connector);
|
||||||
|
else
|
||||||
|
radeon_legacy_backlight_init(radeon_encoder, connector);
|
||||||
|
rdev->mode_info.bl_encoder = radeon_encoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
radeon_link_encoder_connector(struct drm_device *dev)
|
radeon_link_encoder_connector(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct radeon_device *rdev = dev->dev_private;
|
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
struct radeon_connector *radeon_connector;
|
struct radeon_connector *radeon_connector;
|
||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
|
@ -174,13 +207,8 @@ radeon_link_encoder_connector(struct drm_device *dev)
|
||||||
radeon_encoder = to_radeon_encoder(encoder);
|
radeon_encoder = to_radeon_encoder(encoder);
|
||||||
if (radeon_encoder->devices & radeon_connector->devices) {
|
if (radeon_encoder->devices & radeon_connector->devices) {
|
||||||
drm_mode_connector_attach_encoder(connector, encoder);
|
drm_mode_connector_attach_encoder(connector, encoder);
|
||||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
|
||||||
if (rdev->is_atom_bios)
|
radeon_encoder_add_backlight(radeon_encoder, connector);
|
||||||
radeon_atom_backlight_init(radeon_encoder, connector);
|
|
||||||
else
|
|
||||||
radeon_legacy_backlight_init(radeon_encoder, connector);
|
|
||||||
rdev->mode_info.bl_encoder = radeon_encoder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6316,17 +6316,17 @@ static inline u32 si_get_ih_wptr(struct radeon_device *rdev)
|
||||||
wptr = RREG32(IH_RB_WPTR);
|
wptr = RREG32(IH_RB_WPTR);
|
||||||
|
|
||||||
if (wptr & RB_OVERFLOW) {
|
if (wptr & RB_OVERFLOW) {
|
||||||
|
wptr &= ~RB_OVERFLOW;
|
||||||
/* When a ring buffer overflow happen start parsing interrupt
|
/* When a ring buffer overflow happen start parsing interrupt
|
||||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||||
* this should allow us to catchup.
|
* this should allow us to catchup.
|
||||||
*/
|
*/
|
||||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
|
||||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||||
tmp = RREG32(IH_RB_CNTL);
|
tmp = RREG32(IH_RB_CNTL);
|
||||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||||
WREG32(IH_RB_CNTL, tmp);
|
WREG32(IH_RB_CNTL, tmp);
|
||||||
wptr &= ~RB_OVERFLOW;
|
|
||||||
}
|
}
|
||||||
return (wptr & rdev->ih.ptr_mask);
|
return (wptr & rdev->ih.ptr_mask);
|
||||||
}
|
}
|
||||||
|
@ -6664,13 +6664,13 @@ restart_ih:
|
||||||
/* wptr/rptr are in bytes! */
|
/* wptr/rptr are in bytes! */
|
||||||
rptr += 16;
|
rptr += 16;
|
||||||
rptr &= rdev->ih.ptr_mask;
|
rptr &= rdev->ih.ptr_mask;
|
||||||
|
WREG32(IH_RB_RPTR, rptr);
|
||||||
}
|
}
|
||||||
if (queue_hotplug)
|
if (queue_hotplug)
|
||||||
schedule_work(&rdev->hotplug_work);
|
schedule_work(&rdev->hotplug_work);
|
||||||
if (queue_thermal && rdev->pm.dpm_enabled)
|
if (queue_thermal && rdev->pm.dpm_enabled)
|
||||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||||
rdev->ih.rptr = rptr;
|
rdev->ih.rptr = rptr;
|
||||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
|
||||||
atomic_set(&rdev->ih.lock, 0);
|
atomic_set(&rdev->ih.lock, 0);
|
||||||
|
|
||||||
/* make sure wptr hasn't changed while processing */
|
/* make sure wptr hasn't changed while processing */
|
||||||
|
|
|
@ -2,11 +2,8 @@
|
||||||
# Makefile for the i2c core.
|
# Makefile for the i2c core.
|
||||||
#
|
#
|
||||||
|
|
||||||
i2ccore-y := i2c-core.o
|
|
||||||
i2ccore-$(CONFIG_ACPI) += i2c-acpi.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
|
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
|
||||||
obj-$(CONFIG_I2C) += i2ccore.o
|
obj-$(CONFIG_I2C) += i2c-core.o
|
||||||
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
|
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
|
||||||
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
|
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
|
||||||
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
|
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
|
||||||
|
|
|
@ -497,7 +497,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
|
||||||
desc->wr_len_cmd = dma_size;
|
desc->wr_len_cmd = dma_size;
|
||||||
desc->control |= ISMT_DESC_BLK;
|
desc->control |= ISMT_DESC_BLK;
|
||||||
priv->dma_buffer[0] = command;
|
priv->dma_buffer[0] = command;
|
||||||
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size);
|
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
|
||||||
} else {
|
} else {
|
||||||
/* Block Read */
|
/* Block Read */
|
||||||
dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n");
|
dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n");
|
||||||
|
@ -525,7 +525,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
|
||||||
desc->wr_len_cmd = dma_size;
|
desc->wr_len_cmd = dma_size;
|
||||||
desc->control |= ISMT_DESC_I2C;
|
desc->control |= ISMT_DESC_I2C;
|
||||||
priv->dma_buffer[0] = command;
|
priv->dma_buffer[0] = command;
|
||||||
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size);
|
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
|
||||||
} else {
|
} else {
|
||||||
/* i2c Block Read */
|
/* i2c Block Read */
|
||||||
dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n");
|
dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n");
|
||||||
|
|
|
@ -429,7 +429,7 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
|
||||||
ret = mxs_i2c_pio_wait_xfer_end(i2c);
|
ret = mxs_i2c_pio_wait_xfer_end(i2c);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(i2c->dev,
|
dev_err(i2c->dev,
|
||||||
"PIO: Failed to send SELECT command!\n");
|
"PIO: Failed to send READ command!\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,8 @@
|
||||||
#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
|
#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
|
||||||
#define RCAR_IRQ_STOP (MST)
|
#define RCAR_IRQ_STOP (MST)
|
||||||
|
|
||||||
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE))
|
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0xFF)
|
||||||
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR))
|
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF)
|
||||||
|
|
||||||
#define ID_LAST_MSG (1 << 0)
|
#define ID_LAST_MSG (1 << 0)
|
||||||
#define ID_IOERROR (1 << 1)
|
#define ID_IOERROR (1 << 1)
|
||||||
|
|
|
@ -433,12 +433,11 @@ static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate)
|
||||||
unsigned long i2c_rate = clk_get_rate(i2c->clk);
|
unsigned long i2c_rate = clk_get_rate(i2c->clk);
|
||||||
unsigned int div;
|
unsigned int div;
|
||||||
|
|
||||||
/* SCL rate = (clk rate) / (8 * DIV) */
|
/* set DIV = DIVH = DIVL
|
||||||
div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);
|
* SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
|
||||||
|
* = (clk rate) / (16 * (DIV + 1))
|
||||||
/* The lower and upper half of the CLKDIV reg describe the length of
|
*/
|
||||||
* SCL low & high periods. */
|
div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;
|
||||||
div = DIV_ROUND_UP(div, 2);
|
|
||||||
|
|
||||||
i2c_writel(i2c, (div << 16) | (div & 0xffff), REG_CLKDIV);
|
i2c_writel(i2c, (div << 16) | (div & 0xffff), REG_CLKDIV);
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,34 +380,33 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
if (!i2c_dev->hw->has_single_clk_source) {
|
if (!i2c_dev->hw->has_single_clk_source) {
|
||||||
ret = clk_prepare_enable(i2c_dev->fast_clk);
|
ret = clk_enable(i2c_dev->fast_clk);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(i2c_dev->dev,
|
dev_err(i2c_dev->dev,
|
||||||
"Enabling fast clk failed, err %d\n", ret);
|
"Enabling fast clk failed, err %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = clk_prepare_enable(i2c_dev->div_clk);
|
ret = clk_enable(i2c_dev->div_clk);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(i2c_dev->dev,
|
dev_err(i2c_dev->dev,
|
||||||
"Enabling div clk failed, err %d\n", ret);
|
"Enabling div clk failed, err %d\n", ret);
|
||||||
clk_disable_unprepare(i2c_dev->fast_clk);
|
clk_disable(i2c_dev->fast_clk);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev)
|
static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev)
|
||||||
{
|
{
|
||||||
clk_disable_unprepare(i2c_dev->div_clk);
|
clk_disable(i2c_dev->div_clk);
|
||||||
if (!i2c_dev->hw->has_single_clk_source)
|
if (!i2c_dev->hw->has_single_clk_source)
|
||||||
clk_disable_unprepare(i2c_dev->fast_clk);
|
clk_disable(i2c_dev->fast_clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
|
|
||||||
u32 clk_divisor;
|
u32 clk_divisor;
|
||||||
|
|
||||||
err = tegra_i2c_clock_enable(i2c_dev);
|
err = tegra_i2c_clock_enable(i2c_dev);
|
||||||
|
@ -428,9 +427,6 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
||||||
i2c_writel(i2c_dev, val, I2C_CNFG);
|
i2c_writel(i2c_dev, val, I2C_CNFG);
|
||||||
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
|
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
|
||||||
|
|
||||||
clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1);
|
|
||||||
clk_set_rate(i2c_dev->div_clk, i2c_dev->bus_clk_rate * clk_multiplier);
|
|
||||||
|
|
||||||
/* Make sure clock divisor programmed correctly */
|
/* Make sure clock divisor programmed correctly */
|
||||||
clk_divisor = i2c_dev->hw->clk_divisor_hs_mode;
|
clk_divisor = i2c_dev->hw->clk_divisor_hs_mode;
|
||||||
clk_divisor |= i2c_dev->hw->clk_divisor_std_fast_mode <<
|
clk_divisor |= i2c_dev->hw->clk_divisor_std_fast_mode <<
|
||||||
|
@ -712,6 +708,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int irq;
|
int irq;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
base = devm_ioremap_resource(&pdev->dev, res);
|
base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
@ -777,17 +774,39 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, i2c_dev);
|
platform_set_drvdata(pdev, i2c_dev);
|
||||||
|
|
||||||
|
if (!i2c_dev->hw->has_single_clk_source) {
|
||||||
|
ret = clk_prepare(i2c_dev->fast_clk);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1);
|
||||||
|
ret = clk_set_rate(i2c_dev->div_clk,
|
||||||
|
i2c_dev->bus_clk_rate * clk_multiplier);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(i2c_dev->dev, "Clock rate change failed %d\n", ret);
|
||||||
|
goto unprepare_fast_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare(i2c_dev->div_clk);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
|
||||||
|
goto unprepare_fast_clk;
|
||||||
|
}
|
||||||
|
|
||||||
ret = tegra_i2c_init(i2c_dev);
|
ret = tegra_i2c_init(i2c_dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to initialize i2c controller");
|
dev_err(&pdev->dev, "Failed to initialize i2c controller");
|
||||||
return ret;
|
goto unprepare_div_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
|
ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
|
||||||
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
|
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
|
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
|
||||||
return ret;
|
goto unprepare_div_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
|
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
|
||||||
|
@ -803,16 +822,30 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
||||||
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
|
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
|
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
|
||||||
return ret;
|
goto unprepare_div_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
unprepare_div_clk:
|
||||||
|
clk_unprepare(i2c_dev->div_clk);
|
||||||
|
|
||||||
|
unprepare_fast_clk:
|
||||||
|
if (!i2c_dev->hw->has_single_clk_source)
|
||||||
|
clk_unprepare(i2c_dev->fast_clk);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_i2c_remove(struct platform_device *pdev)
|
static int tegra_i2c_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
|
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
|
||||||
i2c_del_adapter(&i2c_dev->adapter);
|
i2c_del_adapter(&i2c_dev->adapter);
|
||||||
|
|
||||||
|
clk_unprepare(i2c_dev->div_clk);
|
||||||
|
if (!i2c_dev->hw->has_single_clk_source)
|
||||||
|
clk_unprepare(i2c_dev->fast_clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,364 +0,0 @@
|
||||||
/*
|
|
||||||
* I2C ACPI code
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Intel Corp
|
|
||||||
*
|
|
||||||
* Author: Lan Tianyu <tianyu.lan@intel.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#define pr_fmt(fmt) "I2C/ACPI : " fmt
|
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/i2c.h>
|
|
||||||
#include <linux/acpi.h>
|
|
||||||
|
|
||||||
struct acpi_i2c_handler_data {
|
|
||||||
struct acpi_connection_info info;
|
|
||||||
struct i2c_adapter *adapter;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gsb_buffer {
|
|
||||||
u8 status;
|
|
||||||
u8 len;
|
|
||||||
union {
|
|
||||||
u16 wdata;
|
|
||||||
u8 bdata;
|
|
||||||
u8 data[0];
|
|
||||||
};
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
|
|
||||||
{
|
|
||||||
struct i2c_board_info *info = data;
|
|
||||||
|
|
||||||
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
|
||||||
struct acpi_resource_i2c_serialbus *sb;
|
|
||||||
|
|
||||||
sb = &ares->data.i2c_serial_bus;
|
|
||||||
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
|
|
||||||
info->addr = sb->slave_address;
|
|
||||||
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
|
|
||||||
info->flags |= I2C_CLIENT_TEN;
|
|
||||||
}
|
|
||||||
} else if (info->irq < 0) {
|
|
||||||
struct resource r;
|
|
||||||
|
|
||||||
if (acpi_dev_resource_interrupt(ares, 0, &r))
|
|
||||||
info->irq = r.start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tell the ACPI core to skip this resource */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
|
|
||||||
void *data, void **return_value)
|
|
||||||
{
|
|
||||||
struct i2c_adapter *adapter = data;
|
|
||||||
struct list_head resource_list;
|
|
||||||
struct i2c_board_info info;
|
|
||||||
struct acpi_device *adev;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (acpi_bus_get_device(handle, &adev))
|
|
||||||
return AE_OK;
|
|
||||||
if (acpi_bus_get_status(adev) || !adev->status.present)
|
|
||||||
return AE_OK;
|
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
|
||||||
info.acpi_node.companion = adev;
|
|
||||||
info.irq = -1;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&resource_list);
|
|
||||||
ret = acpi_dev_get_resources(adev, &resource_list,
|
|
||||||
acpi_i2c_add_resource, &info);
|
|
||||||
acpi_dev_free_resource_list(&resource_list);
|
|
||||||
|
|
||||||
if (ret < 0 || !info.addr)
|
|
||||||
return AE_OK;
|
|
||||||
|
|
||||||
adev->power.flags.ignore_parent = true;
|
|
||||||
strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
|
|
||||||
if (!i2c_new_device(adapter, &info)) {
|
|
||||||
adev->power.flags.ignore_parent = false;
|
|
||||||
dev_err(&adapter->dev,
|
|
||||||
"failed to add I2C device %s from ACPI\n",
|
|
||||||
dev_name(&adev->dev));
|
|
||||||
}
|
|
||||||
|
|
||||||
return AE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
|
|
||||||
* @adap: pointer to adapter
|
|
||||||
*
|
|
||||||
* Enumerate all I2C slave devices behind this adapter by walking the ACPI
|
|
||||||
* namespace. When a device is found it will be added to the Linux device
|
|
||||||
* model and bound to the corresponding ACPI handle.
|
|
||||||
*/
|
|
||||||
void acpi_i2c_register_devices(struct i2c_adapter *adap)
|
|
||||||
{
|
|
||||||
acpi_handle handle;
|
|
||||||
acpi_status status;
|
|
||||||
|
|
||||||
if (!adap->dev.parent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
handle = ACPI_HANDLE(adap->dev.parent);
|
|
||||||
if (!handle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
|
||||||
acpi_i2c_add_device, NULL,
|
|
||||||
adap, NULL);
|
|
||||||
if (ACPI_FAILURE(status))
|
|
||||||
dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_I2C_OPREGION
|
|
||||||
static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
|
|
||||||
u8 cmd, u8 *data, u8 data_len)
|
|
||||||
{
|
|
||||||
|
|
||||||
struct i2c_msg msgs[2];
|
|
||||||
int ret;
|
|
||||||
u8 *buffer;
|
|
||||||
|
|
||||||
buffer = kzalloc(data_len, GFP_KERNEL);
|
|
||||||
if (!buffer)
|
|
||||||
return AE_NO_MEMORY;
|
|
||||||
|
|
||||||
msgs[0].addr = client->addr;
|
|
||||||
msgs[0].flags = client->flags;
|
|
||||||
msgs[0].len = 1;
|
|
||||||
msgs[0].buf = &cmd;
|
|
||||||
|
|
||||||
msgs[1].addr = client->addr;
|
|
||||||
msgs[1].flags = client->flags | I2C_M_RD;
|
|
||||||
msgs[1].len = data_len;
|
|
||||||
msgs[1].buf = buffer;
|
|
||||||
|
|
||||||
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
|
||||||
if (ret < 0)
|
|
||||||
dev_err(&client->adapter->dev, "i2c read failed\n");
|
|
||||||
else
|
|
||||||
memcpy(data, buffer, data_len);
|
|
||||||
|
|
||||||
kfree(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
|
|
||||||
u8 cmd, u8 *data, u8 data_len)
|
|
||||||
{
|
|
||||||
|
|
||||||
struct i2c_msg msgs[1];
|
|
||||||
u8 *buffer;
|
|
||||||
int ret = AE_OK;
|
|
||||||
|
|
||||||
buffer = kzalloc(data_len + 1, GFP_KERNEL);
|
|
||||||
if (!buffer)
|
|
||||||
return AE_NO_MEMORY;
|
|
||||||
|
|
||||||
buffer[0] = cmd;
|
|
||||||
memcpy(buffer + 1, data, data_len);
|
|
||||||
|
|
||||||
msgs[0].addr = client->addr;
|
|
||||||
msgs[0].flags = client->flags;
|
|
||||||
msgs[0].len = data_len + 1;
|
|
||||||
msgs[0].buf = buffer;
|
|
||||||
|
|
||||||
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
|
||||||
if (ret < 0)
|
|
||||||
dev_err(&client->adapter->dev, "i2c write failed\n");
|
|
||||||
|
|
||||||
kfree(buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static acpi_status
|
|
||||||
acpi_i2c_space_handler(u32 function, acpi_physical_address command,
|
|
||||||
u32 bits, u64 *value64,
|
|
||||||
void *handler_context, void *region_context)
|
|
||||||
{
|
|
||||||
struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
|
|
||||||
struct acpi_i2c_handler_data *data = handler_context;
|
|
||||||
struct acpi_connection_info *info = &data->info;
|
|
||||||
struct acpi_resource_i2c_serialbus *sb;
|
|
||||||
struct i2c_adapter *adapter = data->adapter;
|
|
||||||
struct i2c_client client;
|
|
||||||
struct acpi_resource *ares;
|
|
||||||
u32 accessor_type = function >> 16;
|
|
||||||
u8 action = function & ACPI_IO_MASK;
|
|
||||||
acpi_status ret = AE_OK;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
|
|
||||||
if (ACPI_FAILURE(ret))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
|
||||||
ret = AE_BAD_PARAMETER;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sb = &ares->data.i2c_serial_bus;
|
|
||||||
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
|
|
||||||
ret = AE_BAD_PARAMETER;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&client, 0, sizeof(client));
|
|
||||||
client.adapter = adapter;
|
|
||||||
client.addr = sb->slave_address;
|
|
||||||
client.flags = 0;
|
|
||||||
|
|
||||||
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
|
|
||||||
client.flags |= I2C_CLIENT_TEN;
|
|
||||||
|
|
||||||
switch (accessor_type) {
|
|
||||||
case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
|
|
||||||
if (action == ACPI_READ) {
|
|
||||||
status = i2c_smbus_read_byte(&client);
|
|
||||||
if (status >= 0) {
|
|
||||||
gsb->bdata = status;
|
|
||||||
status = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status = i2c_smbus_write_byte(&client, gsb->bdata);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_GSB_ACCESS_ATTRIB_BYTE:
|
|
||||||
if (action == ACPI_READ) {
|
|
||||||
status = i2c_smbus_read_byte_data(&client, command);
|
|
||||||
if (status >= 0) {
|
|
||||||
gsb->bdata = status;
|
|
||||||
status = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status = i2c_smbus_write_byte_data(&client, command,
|
|
||||||
gsb->bdata);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_GSB_ACCESS_ATTRIB_WORD:
|
|
||||||
if (action == ACPI_READ) {
|
|
||||||
status = i2c_smbus_read_word_data(&client, command);
|
|
||||||
if (status >= 0) {
|
|
||||||
gsb->wdata = status;
|
|
||||||
status = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status = i2c_smbus_write_word_data(&client, command,
|
|
||||||
gsb->wdata);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
|
|
||||||
if (action == ACPI_READ) {
|
|
||||||
status = i2c_smbus_read_block_data(&client, command,
|
|
||||||
gsb->data);
|
|
||||||
if (status >= 0) {
|
|
||||||
gsb->len = status;
|
|
||||||
status = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status = i2c_smbus_write_block_data(&client, command,
|
|
||||||
gsb->len, gsb->data);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
|
|
||||||
if (action == ACPI_READ) {
|
|
||||||
status = acpi_gsb_i2c_read_bytes(&client, command,
|
|
||||||
gsb->data, info->access_length);
|
|
||||||
if (status > 0)
|
|
||||||
status = 0;
|
|
||||||
} else {
|
|
||||||
status = acpi_gsb_i2c_write_bytes(&client, command,
|
|
||||||
gsb->data, info->access_length);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
|
|
||||||
ret = AE_BAD_PARAMETER;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
gsb->status = status;
|
|
||||||
|
|
||||||
err:
|
|
||||||
ACPI_FREE(ares);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
|
|
||||||
{
|
|
||||||
acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
|
|
||||||
struct acpi_i2c_handler_data *data;
|
|
||||||
acpi_status status;
|
|
||||||
|
|
||||||
if (!handle)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
data = kzalloc(sizeof(struct acpi_i2c_handler_data),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
data->adapter = adapter;
|
|
||||||
status = acpi_bus_attach_private_data(handle, (void *)data);
|
|
||||||
if (ACPI_FAILURE(status)) {
|
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = acpi_install_address_space_handler(handle,
|
|
||||||
ACPI_ADR_SPACE_GSBUS,
|
|
||||||
&acpi_i2c_space_handler,
|
|
||||||
NULL,
|
|
||||||
data);
|
|
||||||
if (ACPI_FAILURE(status)) {
|
|
||||||
dev_err(&adapter->dev, "Error installing i2c space handler\n");
|
|
||||||
acpi_bus_detach_private_data(handle);
|
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
|
|
||||||
{
|
|
||||||
acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
|
|
||||||
struct acpi_i2c_handler_data *data;
|
|
||||||
acpi_status status;
|
|
||||||
|
|
||||||
if (!handle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
acpi_remove_address_space_handler(handle,
|
|
||||||
ACPI_ADR_SPACE_GSBUS,
|
|
||||||
&acpi_i2c_space_handler);
|
|
||||||
|
|
||||||
status = acpi_bus_get_private_data(handle, (void **)&data);
|
|
||||||
if (ACPI_SUCCESS(status))
|
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
acpi_bus_detach_private_data(handle);
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -27,6 +27,8 @@
|
||||||
OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
|
OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
|
||||||
(based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
|
(based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
|
||||||
(c) 2013 Wolfram Sang <wsa@the-dreams.de>
|
(c) 2013 Wolfram Sang <wsa@the-dreams.de>
|
||||||
|
I2C ACPI code Copyright (C) 2014 Intel Corp
|
||||||
|
Author: Lan Tianyu <tianyu.lan@intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -78,6 +80,368 @@ void i2c_transfer_trace_unreg(void)
|
||||||
static_key_slow_dec(&i2c_trace_msg);
|
static_key_slow_dec(&i2c_trace_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_ACPI)
|
||||||
|
struct acpi_i2c_handler_data {
|
||||||
|
struct acpi_connection_info info;
|
||||||
|
struct i2c_adapter *adapter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gsb_buffer {
|
||||||
|
u8 status;
|
||||||
|
u8 len;
|
||||||
|
union {
|
||||||
|
u16 wdata;
|
||||||
|
u8 bdata;
|
||||||
|
u8 data[0];
|
||||||
|
};
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
|
||||||
|
{
|
||||||
|
struct i2c_board_info *info = data;
|
||||||
|
|
||||||
|
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
||||||
|
struct acpi_resource_i2c_serialbus *sb;
|
||||||
|
|
||||||
|
sb = &ares->data.i2c_serial_bus;
|
||||||
|
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
|
||||||
|
info->addr = sb->slave_address;
|
||||||
|
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
|
||||||
|
info->flags |= I2C_CLIENT_TEN;
|
||||||
|
}
|
||||||
|
} else if (info->irq < 0) {
|
||||||
|
struct resource r;
|
||||||
|
|
||||||
|
if (acpi_dev_resource_interrupt(ares, 0, &r))
|
||||||
|
info->irq = r.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell the ACPI core to skip this resource */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
|
||||||
|
void *data, void **return_value)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *adapter = data;
|
||||||
|
struct list_head resource_list;
|
||||||
|
struct i2c_board_info info;
|
||||||
|
struct acpi_device *adev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (acpi_bus_get_device(handle, &adev))
|
||||||
|
return AE_OK;
|
||||||
|
if (acpi_bus_get_status(adev) || !adev->status.present)
|
||||||
|
return AE_OK;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
info.acpi_node.companion = adev;
|
||||||
|
info.irq = -1;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&resource_list);
|
||||||
|
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||||
|
acpi_i2c_add_resource, &info);
|
||||||
|
acpi_dev_free_resource_list(&resource_list);
|
||||||
|
|
||||||
|
if (ret < 0 || !info.addr)
|
||||||
|
return AE_OK;
|
||||||
|
|
||||||
|
adev->power.flags.ignore_parent = true;
|
||||||
|
strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
|
||||||
|
if (!i2c_new_device(adapter, &info)) {
|
||||||
|
adev->power.flags.ignore_parent = false;
|
||||||
|
dev_err(&adapter->dev,
|
||||||
|
"failed to add I2C device %s from ACPI\n",
|
||||||
|
dev_name(&adev->dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
return AE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
|
||||||
|
* @adap: pointer to adapter
|
||||||
|
*
|
||||||
|
* Enumerate all I2C slave devices behind this adapter by walking the ACPI
|
||||||
|
* namespace. When a device is found it will be added to the Linux device
|
||||||
|
* model and bound to the corresponding ACPI handle.
|
||||||
|
*/
|
||||||
|
static void acpi_i2c_register_devices(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
acpi_handle handle;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
if (!adap->dev.parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
handle = ACPI_HANDLE(adap->dev.parent);
|
||||||
|
if (!handle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
|
||||||
|
acpi_i2c_add_device, NULL,
|
||||||
|
adap, NULL);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CONFIG_ACPI */
|
||||||
|
static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { }
|
||||||
|
#endif /* CONFIG_ACPI */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI_I2C_OPREGION
|
||||||
|
static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
|
||||||
|
u8 cmd, u8 *data, u8 data_len)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct i2c_msg msgs[2];
|
||||||
|
int ret;
|
||||||
|
u8 *buffer;
|
||||||
|
|
||||||
|
buffer = kzalloc(data_len, GFP_KERNEL);
|
||||||
|
if (!buffer)
|
||||||
|
return AE_NO_MEMORY;
|
||||||
|
|
||||||
|
msgs[0].addr = client->addr;
|
||||||
|
msgs[0].flags = client->flags;
|
||||||
|
msgs[0].len = 1;
|
||||||
|
msgs[0].buf = &cmd;
|
||||||
|
|
||||||
|
msgs[1].addr = client->addr;
|
||||||
|
msgs[1].flags = client->flags | I2C_M_RD;
|
||||||
|
msgs[1].len = data_len;
|
||||||
|
msgs[1].buf = buffer;
|
||||||
|
|
||||||
|
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(&client->adapter->dev, "i2c read failed\n");
|
||||||
|
else
|
||||||
|
memcpy(data, buffer, data_len);
|
||||||
|
|
||||||
|
kfree(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
|
||||||
|
u8 cmd, u8 *data, u8 data_len)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct i2c_msg msgs[1];
|
||||||
|
u8 *buffer;
|
||||||
|
int ret = AE_OK;
|
||||||
|
|
||||||
|
buffer = kzalloc(data_len + 1, GFP_KERNEL);
|
||||||
|
if (!buffer)
|
||||||
|
return AE_NO_MEMORY;
|
||||||
|
|
||||||
|
buffer[0] = cmd;
|
||||||
|
memcpy(buffer + 1, data, data_len);
|
||||||
|
|
||||||
|
msgs[0].addr = client->addr;
|
||||||
|
msgs[0].flags = client->flags;
|
||||||
|
msgs[0].len = data_len + 1;
|
||||||
|
msgs[0].buf = buffer;
|
||||||
|
|
||||||
|
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(&client->adapter->dev, "i2c write failed\n");
|
||||||
|
|
||||||
|
kfree(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static acpi_status
|
||||||
|
acpi_i2c_space_handler(u32 function, acpi_physical_address command,
|
||||||
|
u32 bits, u64 *value64,
|
||||||
|
void *handler_context, void *region_context)
|
||||||
|
{
|
||||||
|
struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
|
||||||
|
struct acpi_i2c_handler_data *data = handler_context;
|
||||||
|
struct acpi_connection_info *info = &data->info;
|
||||||
|
struct acpi_resource_i2c_serialbus *sb;
|
||||||
|
struct i2c_adapter *adapter = data->adapter;
|
||||||
|
struct i2c_client client;
|
||||||
|
struct acpi_resource *ares;
|
||||||
|
u32 accessor_type = function >> 16;
|
||||||
|
u8 action = function & ACPI_IO_MASK;
|
||||||
|
acpi_status ret = AE_OK;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
|
||||||
|
if (ACPI_FAILURE(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
||||||
|
ret = AE_BAD_PARAMETER;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb = &ares->data.i2c_serial_bus;
|
||||||
|
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
|
||||||
|
ret = AE_BAD_PARAMETER;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&client, 0, sizeof(client));
|
||||||
|
client.adapter = adapter;
|
||||||
|
client.addr = sb->slave_address;
|
||||||
|
client.flags = 0;
|
||||||
|
|
||||||
|
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
|
||||||
|
client.flags |= I2C_CLIENT_TEN;
|
||||||
|
|
||||||
|
switch (accessor_type) {
|
||||||
|
case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
|
||||||
|
if (action == ACPI_READ) {
|
||||||
|
status = i2c_smbus_read_byte(&client);
|
||||||
|
if (status >= 0) {
|
||||||
|
gsb->bdata = status;
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = i2c_smbus_write_byte(&client, gsb->bdata);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_GSB_ACCESS_ATTRIB_BYTE:
|
||||||
|
if (action == ACPI_READ) {
|
||||||
|
status = i2c_smbus_read_byte_data(&client, command);
|
||||||
|
if (status >= 0) {
|
||||||
|
gsb->bdata = status;
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = i2c_smbus_write_byte_data(&client, command,
|
||||||
|
gsb->bdata);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_GSB_ACCESS_ATTRIB_WORD:
|
||||||
|
if (action == ACPI_READ) {
|
||||||
|
status = i2c_smbus_read_word_data(&client, command);
|
||||||
|
if (status >= 0) {
|
||||||
|
gsb->wdata = status;
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = i2c_smbus_write_word_data(&client, command,
|
||||||
|
gsb->wdata);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
|
||||||
|
if (action == ACPI_READ) {
|
||||||
|
status = i2c_smbus_read_block_data(&client, command,
|
||||||
|
gsb->data);
|
||||||
|
if (status >= 0) {
|
||||||
|
gsb->len = status;
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = i2c_smbus_write_block_data(&client, command,
|
||||||
|
gsb->len, gsb->data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
|
||||||
|
if (action == ACPI_READ) {
|
||||||
|
status = acpi_gsb_i2c_read_bytes(&client, command,
|
||||||
|
gsb->data, info->access_length);
|
||||||
|
if (status > 0)
|
||||||
|
status = 0;
|
||||||
|
} else {
|
||||||
|
status = acpi_gsb_i2c_write_bytes(&client, command,
|
||||||
|
gsb->data, info->access_length);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
|
||||||
|
ret = AE_BAD_PARAMETER;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsb->status = status;
|
||||||
|
|
||||||
|
err:
|
||||||
|
ACPI_FREE(ares);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
|
||||||
|
{
|
||||||
|
acpi_handle handle;
|
||||||
|
struct acpi_i2c_handler_data *data;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
if (!adapter->dev.parent)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
handle = ACPI_HANDLE(adapter->dev.parent);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
data = kzalloc(sizeof(struct acpi_i2c_handler_data),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data->adapter = adapter;
|
||||||
|
status = acpi_bus_attach_private_data(handle, (void *)data);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
kfree(data);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = acpi_install_address_space_handler(handle,
|
||||||
|
ACPI_ADR_SPACE_GSBUS,
|
||||||
|
&acpi_i2c_space_handler,
|
||||||
|
NULL,
|
||||||
|
data);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
dev_err(&adapter->dev, "Error installing i2c space handler\n");
|
||||||
|
acpi_bus_detach_private_data(handle);
|
||||||
|
kfree(data);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
|
||||||
|
{
|
||||||
|
acpi_handle handle;
|
||||||
|
struct acpi_i2c_handler_data *data;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
if (!adapter->dev.parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
handle = ACPI_HANDLE(adapter->dev.parent);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
acpi_remove_address_space_handler(handle,
|
||||||
|
ACPI_ADR_SPACE_GSBUS,
|
||||||
|
&acpi_i2c_space_handler);
|
||||||
|
|
||||||
|
status = acpi_bus_get_private_data(handle, (void **)&data);
|
||||||
|
if (ACPI_SUCCESS(status))
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
|
acpi_bus_detach_private_data(handle);
|
||||||
|
}
|
||||||
|
#else /* CONFIG_ACPI_I2C_OPREGION */
|
||||||
|
static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
|
||||||
|
{ return 0; }
|
||||||
|
#endif /* CONFIG_ACPI_I2C_OPREGION */
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
|
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
|
||||||
|
|
|
@ -465,6 +465,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/* Asus X450LCP */
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
/* Avatar AVIU-145A6 */
|
/* Avatar AVIU-145A6 */
|
||||||
.matches = {
|
.matches = {
|
||||||
|
|
|
@ -3236,8 +3236,9 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
||||||
|
|
||||||
skb->protocol = eth_type_trans(skb, bp->dev);
|
skb->protocol = eth_type_trans(skb, bp->dev);
|
||||||
|
|
||||||
if ((len > (bp->dev->mtu + ETH_HLEN)) &&
|
if (len > (bp->dev->mtu + ETH_HLEN) &&
|
||||||
(ntohs(skb->protocol) != 0x8100)) {
|
skb->protocol != htons(0x8100) &&
|
||||||
|
skb->protocol != htons(ETH_P_8021AD)) {
|
||||||
|
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
goto next_rx;
|
goto next_rx;
|
||||||
|
|
|
@ -6918,7 +6918,8 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
|
||||||
skb->protocol = eth_type_trans(skb, tp->dev);
|
skb->protocol = eth_type_trans(skb, tp->dev);
|
||||||
|
|
||||||
if (len > (tp->dev->mtu + ETH_HLEN) &&
|
if (len > (tp->dev->mtu + ETH_HLEN) &&
|
||||||
skb->protocol != htons(ETH_P_8021Q)) {
|
skb->protocol != htons(ETH_P_8021Q) &&
|
||||||
|
skb->protocol != htons(ETH_P_8021AD)) {
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
goto drop_it_no_recycle;
|
goto drop_it_no_recycle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/of_mdio.h>
|
#include <linux/of_mdio.h>
|
||||||
#include <linux/of_net.h>
|
#include <linux/of_net.h>
|
||||||
#include <linux/pinctrl/consumer.h>
|
|
||||||
|
|
||||||
#include "macb.h"
|
#include "macb.h"
|
||||||
|
|
||||||
|
@ -2071,7 +2070,6 @@ static int __init macb_probe(struct platform_device *pdev)
|
||||||
struct phy_device *phydev;
|
struct phy_device *phydev;
|
||||||
u32 config;
|
u32 config;
|
||||||
int err = -ENXIO;
|
int err = -ENXIO;
|
||||||
struct pinctrl *pinctrl;
|
|
||||||
const char *mac;
|
const char *mac;
|
||||||
|
|
||||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
@ -2080,15 +2078,6 @@ static int __init macb_probe(struct platform_device *pdev)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
|
||||||
if (IS_ERR(pinctrl)) {
|
|
||||||
err = PTR_ERR(pinctrl);
|
|
||||||
if (err == -EPROBE_DEFER)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
dev_warn(&pdev->dev, "No pinctrl provided\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
dev = alloc_etherdev(sizeof(*bp));
|
dev = alloc_etherdev(sizeof(*bp));
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
|
|
@ -78,13 +78,13 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
|
||||||
#endif /* CONFIG_PCI_MSI */
|
#endif /* CONFIG_PCI_MSI */
|
||||||
|
|
||||||
static uint8_t num_vfs[3] = {0, 0, 0};
|
static uint8_t num_vfs[3] = {0, 0, 0};
|
||||||
static int num_vfs_argc = 3;
|
static int num_vfs_argc;
|
||||||
module_param_array(num_vfs, byte , &num_vfs_argc, 0444);
|
module_param_array(num_vfs, byte , &num_vfs_argc, 0444);
|
||||||
MODULE_PARM_DESC(num_vfs, "enable #num_vfs functions if num_vfs > 0\n"
|
MODULE_PARM_DESC(num_vfs, "enable #num_vfs functions if num_vfs > 0\n"
|
||||||
"num_vfs=port1,port2,port1+2");
|
"num_vfs=port1,port2,port1+2");
|
||||||
|
|
||||||
static uint8_t probe_vf[3] = {0, 0, 0};
|
static uint8_t probe_vf[3] = {0, 0, 0};
|
||||||
static int probe_vfs_argc = 3;
|
static int probe_vfs_argc;
|
||||||
module_param_array(probe_vf, byte, &probe_vfs_argc, 0444);
|
module_param_array(probe_vf, byte, &probe_vfs_argc, 0444);
|
||||||
MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)\n"
|
MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)\n"
|
||||||
"probe_vf=port1,port2,port1+2");
|
"probe_vf=port1,port2,port1+2");
|
||||||
|
|
|
@ -135,6 +135,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
|
||||||
int i, j;
|
int i, j;
|
||||||
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
|
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
|
||||||
|
|
||||||
|
spin_lock(&adapter->tx_clean_lock);
|
||||||
cmd_buf = tx_ring->cmd_buf_arr;
|
cmd_buf = tx_ring->cmd_buf_arr;
|
||||||
for (i = 0; i < tx_ring->num_desc; i++) {
|
for (i = 0; i < tx_ring->num_desc; i++) {
|
||||||
buffrag = cmd_buf->frag_array;
|
buffrag = cmd_buf->frag_array;
|
||||||
|
@ -158,6 +159,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
|
||||||
}
|
}
|
||||||
cmd_buf++;
|
cmd_buf++;
|
||||||
}
|
}
|
||||||
|
spin_unlock(&adapter->tx_clean_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void netxen_free_sw_resources(struct netxen_adapter *adapter)
|
void netxen_free_sw_resources(struct netxen_adapter *adapter)
|
||||||
|
@ -1792,9 +1794,9 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count && netif_running(netdev)) {
|
tx_ring->sw_consumer = sw_consumer;
|
||||||
tx_ring->sw_consumer = sw_consumer;
|
|
||||||
|
|
||||||
|
if (count && netif_running(netdev)) {
|
||||||
smp_mb();
|
smp_mb();
|
||||||
|
|
||||||
if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
|
if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
|
||||||
|
|
|
@ -1186,7 +1186,6 @@ __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
smp_mb();
|
smp_mb();
|
||||||
spin_lock(&adapter->tx_clean_lock);
|
|
||||||
netif_carrier_off(netdev);
|
netif_carrier_off(netdev);
|
||||||
netif_tx_disable(netdev);
|
netif_tx_disable(netdev);
|
||||||
|
|
||||||
|
@ -1204,7 +1203,6 @@ __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
|
||||||
netxen_napi_disable(adapter);
|
netxen_napi_disable(adapter);
|
||||||
|
|
||||||
netxen_release_tx_buffers(adapter);
|
netxen_release_tx_buffers(adapter);
|
||||||
spin_unlock(&adapter->tx_clean_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Usage: During suspend and firmware recovery module */
|
/* Usage: During suspend and firmware recovery module */
|
||||||
|
|
|
@ -1177,9 +1177,8 @@ static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
u32 idc_params, val;
|
u32 idc_params, val;
|
||||||
|
|
||||||
if (qlcnic_83xx_lockless_flash_read32(adapter,
|
if (qlcnic_83xx_flash_read32(adapter, QLC_83XX_IDC_FLASH_PARAM_ADDR,
|
||||||
QLC_83XX_IDC_FLASH_PARAM_ADDR,
|
(u8 *)&idc_params, 1)) {
|
||||||
(u8 *)&idc_params, 1)) {
|
|
||||||
dev_info(&adapter->pdev->dev,
|
dev_info(&adapter->pdev->dev,
|
||||||
"%s:failed to get IDC params from flash\n", __func__);
|
"%s:failed to get IDC params from flash\n", __func__);
|
||||||
adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS;
|
adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS;
|
||||||
|
|
|
@ -1333,21 +1333,21 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
struct qlcnic_esw_statistics port_stats;
|
struct qlcnic_esw_statistics port_stats;
|
||||||
struct qlcnic_mac_statistics mac_stats;
|
struct qlcnic_mac_statistics mac_stats;
|
||||||
int index, ret, length, size, tx_size, ring;
|
int index, ret, length, size, ring;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
tx_size = adapter->drv_tx_rings * QLCNIC_TX_STATS_LEN;
|
memset(data, 0, stats->n_stats * sizeof(u64));
|
||||||
|
|
||||||
memset(data, 0, tx_size * sizeof(u64));
|
|
||||||
for (ring = 0, index = 0; ring < adapter->drv_tx_rings; ring++) {
|
for (ring = 0, index = 0; ring < adapter->drv_tx_rings; ring++) {
|
||||||
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
|
if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
data = qlcnic_fill_tx_queue_stats(data, tx_ring);
|
data = qlcnic_fill_tx_queue_stats(data, tx_ring);
|
||||||
qlcnic_update_stats(adapter);
|
qlcnic_update_stats(adapter);
|
||||||
|
} else {
|
||||||
|
data += QLCNIC_TX_STATS_LEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(data, 0, stats->n_stats * sizeof(u64));
|
|
||||||
length = QLCNIC_STATS_LEN;
|
length = QLCNIC_STATS_LEN;
|
||||||
for (index = 0; index < length; index++) {
|
for (index = 0; index < length; index++) {
|
||||||
p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset;
|
p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset;
|
||||||
|
|
|
@ -2786,8 +2786,15 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
|
||||||
if (IS_ERR(priv->stmmac_clk)) {
|
if (IS_ERR(priv->stmmac_clk)) {
|
||||||
dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
|
dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
|
||||||
__func__);
|
__func__);
|
||||||
ret = PTR_ERR(priv->stmmac_clk);
|
/* If failed to obtain stmmac_clk and specific clk_csr value
|
||||||
goto error_clk_get;
|
* is NOT passed from the platform, probe fail.
|
||||||
|
*/
|
||||||
|
if (!priv->plat->clk_csr) {
|
||||||
|
ret = PTR_ERR(priv->stmmac_clk);
|
||||||
|
goto error_clk_get;
|
||||||
|
} else {
|
||||||
|
priv->stmmac_clk = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clk_prepare_enable(priv->stmmac_clk);
|
clk_prepare_enable(priv->stmmac_clk);
|
||||||
|
|
||||||
|
|
|
@ -387,6 +387,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||||
int hdr_offset;
|
int hdr_offset;
|
||||||
u32 net_trans_info;
|
u32 net_trans_info;
|
||||||
u32 hash;
|
u32 hash;
|
||||||
|
u32 skb_length = skb->len;
|
||||||
|
|
||||||
|
|
||||||
/* We will atmost need two pages to describe the rndis
|
/* We will atmost need two pages to describe the rndis
|
||||||
|
@ -562,7 +563,7 @@ do_send:
|
||||||
|
|
||||||
drop:
|
drop:
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
net->stats.tx_bytes += skb->len;
|
net->stats.tx_bytes += skb_length;
|
||||||
net->stats.tx_packets++;
|
net->stats.tx_packets++;
|
||||||
} else {
|
} else {
|
||||||
kfree(packet);
|
kfree(packet);
|
||||||
|
|
|
@ -112,17 +112,15 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Requires RTNL */
|
||||||
static int macvtap_set_queue(struct net_device *dev, struct file *file,
|
static int macvtap_set_queue(struct net_device *dev, struct file *file,
|
||||||
struct macvtap_queue *q)
|
struct macvtap_queue *q)
|
||||||
{
|
{
|
||||||
struct macvlan_dev *vlan = netdev_priv(dev);
|
struct macvlan_dev *vlan = netdev_priv(dev);
|
||||||
int err = -EBUSY;
|
|
||||||
|
|
||||||
rtnl_lock();
|
|
||||||
if (vlan->numqueues == MAX_MACVTAP_QUEUES)
|
if (vlan->numqueues == MAX_MACVTAP_QUEUES)
|
||||||
goto out;
|
return -EBUSY;
|
||||||
|
|
||||||
err = 0;
|
|
||||||
rcu_assign_pointer(q->vlan, vlan);
|
rcu_assign_pointer(q->vlan, vlan);
|
||||||
rcu_assign_pointer(vlan->taps[vlan->numvtaps], q);
|
rcu_assign_pointer(vlan->taps[vlan->numvtaps], q);
|
||||||
sock_hold(&q->sk);
|
sock_hold(&q->sk);
|
||||||
|
@ -136,9 +134,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file,
|
||||||
vlan->numvtaps++;
|
vlan->numvtaps++;
|
||||||
vlan->numqueues++;
|
vlan->numqueues++;
|
||||||
|
|
||||||
out:
|
return 0;
|
||||||
rtnl_unlock();
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int macvtap_disable_queue(struct macvtap_queue *q)
|
static int macvtap_disable_queue(struct macvtap_queue *q)
|
||||||
|
@ -454,11 +450,12 @@ static void macvtap_sock_destruct(struct sock *sk)
|
||||||
static int macvtap_open(struct inode *inode, struct file *file)
|
static int macvtap_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct net *net = current->nsproxy->net_ns;
|
struct net *net = current->nsproxy->net_ns;
|
||||||
struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode));
|
struct net_device *dev;
|
||||||
struct macvtap_queue *q;
|
struct macvtap_queue *q;
|
||||||
int err;
|
int err = -ENODEV;
|
||||||
|
|
||||||
err = -ENODEV;
|
rtnl_lock();
|
||||||
|
dev = dev_get_by_macvtap_minor(iminor(inode));
|
||||||
if (!dev)
|
if (!dev)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -498,6 +495,7 @@ out:
|
||||||
if (dev)
|
if (dev)
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
|
|
||||||
|
rtnl_unlock();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <linux/mdio.h>
|
#include <linux/mdio.h>
|
||||||
|
|
||||||
/* Version Information */
|
/* Version Information */
|
||||||
#define DRIVER_VERSION "v1.06.0 (2014/03/03)"
|
#define DRIVER_VERSION "v1.06.1 (2014/10/01)"
|
||||||
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
|
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
|
||||||
#define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
|
#define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
|
||||||
#define MODULENAME "r8152"
|
#define MODULENAME "r8152"
|
||||||
|
@ -1979,10 +1979,34 @@ static void rxdy_gated_en(struct r8152 *tp, bool enable)
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rtl_start_rx(struct r8152 *tp)
|
||||||
|
{
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&tp->rx_done);
|
||||||
|
for (i = 0; i < RTL8152_MAX_RX; i++) {
|
||||||
|
INIT_LIST_HEAD(&tp->rx_info[i].list);
|
||||||
|
ret = r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl_stop_rx(struct r8152 *tp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < RTL8152_MAX_RX; i++)
|
||||||
|
usb_kill_urb(tp->rx_info[i].urb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int rtl_enable(struct r8152 *tp)
|
static int rtl_enable(struct r8152 *tp)
|
||||||
{
|
{
|
||||||
u32 ocp_data;
|
u32 ocp_data;
|
||||||
int i, ret;
|
|
||||||
|
|
||||||
r8152b_reset_packet_filter(tp);
|
r8152b_reset_packet_filter(tp);
|
||||||
|
|
||||||
|
@ -1992,14 +2016,7 @@ static int rtl_enable(struct r8152 *tp)
|
||||||
|
|
||||||
rxdy_gated_en(tp, false);
|
rxdy_gated_en(tp, false);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&tp->rx_done);
|
return rtl_start_rx(tp);
|
||||||
ret = 0;
|
|
||||||
for (i = 0; i < RTL8152_MAX_RX; i++) {
|
|
||||||
INIT_LIST_HEAD(&tp->rx_info[i].list);
|
|
||||||
ret |= r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl8152_enable(struct r8152 *tp)
|
static int rtl8152_enable(struct r8152 *tp)
|
||||||
|
@ -2083,8 +2100,7 @@ static void rtl_disable(struct r8152 *tp)
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < RTL8152_MAX_RX; i++)
|
rtl_stop_rx(tp);
|
||||||
usb_kill_urb(tp->rx_info[i].urb);
|
|
||||||
|
|
||||||
rtl8152_nic_reset(tp);
|
rtl8152_nic_reset(tp);
|
||||||
}
|
}
|
||||||
|
@ -2243,28 +2259,6 @@ static void rtl_phy_reset(struct r8152 *tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtl_clear_bp(struct r8152 *tp)
|
|
||||||
{
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_0, 0);
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_2, 0);
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_4, 0);
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_6, 0);
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_0, 0);
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0);
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0);
|
|
||||||
ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0);
|
|
||||||
usleep_range(3000, 6000);
|
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0);
|
|
||||||
ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void r8153_clear_bp(struct r8152 *tp)
|
|
||||||
{
|
|
||||||
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
|
|
||||||
ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0);
|
|
||||||
rtl_clear_bp(tp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void r8153_teredo_off(struct r8152 *tp)
|
static void r8153_teredo_off(struct r8152 *tp)
|
||||||
{
|
{
|
||||||
u32 ocp_data;
|
u32 ocp_data;
|
||||||
|
@ -2307,8 +2301,6 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp)
|
||||||
r8152_mdio_write(tp, MII_BMCR, data);
|
r8152_mdio_write(tp, MII_BMCR, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtl_clear_bp(tp);
|
|
||||||
|
|
||||||
set_bit(PHY_RESET, &tp->flags);
|
set_bit(PHY_RESET, &tp->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2455,8 +2447,6 @@ static void r8153_hw_phy_cfg(struct r8152 *tp)
|
||||||
r8152_mdio_write(tp, MII_BMCR, data);
|
r8152_mdio_write(tp, MII_BMCR, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
r8153_clear_bp(tp);
|
|
||||||
|
|
||||||
if (tp->version == RTL_VER_03) {
|
if (tp->version == RTL_VER_03) {
|
||||||
data = ocp_reg_read(tp, OCP_EEE_CFG);
|
data = ocp_reg_read(tp, OCP_EEE_CFG);
|
||||||
data &= ~CTAP_SHORT_EN;
|
data &= ~CTAP_SHORT_EN;
|
||||||
|
@ -3181,13 +3171,14 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
|
||||||
clear_bit(WORK_ENABLE, &tp->flags);
|
clear_bit(WORK_ENABLE, &tp->flags);
|
||||||
usb_kill_urb(tp->intr_urb);
|
usb_kill_urb(tp->intr_urb);
|
||||||
cancel_delayed_work_sync(&tp->schedule);
|
cancel_delayed_work_sync(&tp->schedule);
|
||||||
|
tasklet_disable(&tp->tl);
|
||||||
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
|
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
|
||||||
|
rtl_stop_rx(tp);
|
||||||
rtl_runtime_suspend_enable(tp, true);
|
rtl_runtime_suspend_enable(tp, true);
|
||||||
} else {
|
} else {
|
||||||
tasklet_disable(&tp->tl);
|
|
||||||
tp->rtl_ops.down(tp);
|
tp->rtl_ops.down(tp);
|
||||||
tasklet_enable(&tp->tl);
|
|
||||||
}
|
}
|
||||||
|
tasklet_enable(&tp->tl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3206,18 +3197,19 @@ static int rtl8152_resume(struct usb_interface *intf)
|
||||||
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
|
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
|
||||||
rtl_runtime_suspend_enable(tp, false);
|
rtl_runtime_suspend_enable(tp, false);
|
||||||
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||||
|
set_bit(WORK_ENABLE, &tp->flags);
|
||||||
if (tp->speed & LINK_STATUS)
|
if (tp->speed & LINK_STATUS)
|
||||||
tp->rtl_ops.disable(tp);
|
rtl_start_rx(tp);
|
||||||
} else {
|
} else {
|
||||||
tp->rtl_ops.up(tp);
|
tp->rtl_ops.up(tp);
|
||||||
rtl8152_set_speed(tp, AUTONEG_ENABLE,
|
rtl8152_set_speed(tp, AUTONEG_ENABLE,
|
||||||
tp->mii.supports_gmii ?
|
tp->mii.supports_gmii ?
|
||||||
SPEED_1000 : SPEED_100,
|
SPEED_1000 : SPEED_100,
|
||||||
DUPLEX_FULL);
|
DUPLEX_FULL);
|
||||||
|
tp->speed = 0;
|
||||||
|
netif_carrier_off(tp->netdev);
|
||||||
|
set_bit(WORK_ENABLE, &tp->flags);
|
||||||
}
|
}
|
||||||
tp->speed = 0;
|
|
||||||
netif_carrier_off(tp->netdev);
|
|
||||||
set_bit(WORK_ENABLE, &tp->flags);
|
|
||||||
usb_submit_urb(tp->intr_urb, GFP_KERNEL);
|
usb_submit_urb(tp->intr_urb, GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3623,7 +3615,7 @@ static void rtl8153_unload(struct r8152 *tp)
|
||||||
if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r8153_power_cut_en(tp, true);
|
r8153_power_cut_en(tp, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
|
static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
|
||||||
|
@ -3788,7 +3780,11 @@ static void rtl8152_disconnect(struct usb_interface *intf)
|
||||||
|
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
if (tp) {
|
if (tp) {
|
||||||
set_bit(RTL8152_UNPLUG, &tp->flags);
|
struct usb_device *udev = tp->udev;
|
||||||
|
|
||||||
|
if (udev->state == USB_STATE_NOTATTACHED)
|
||||||
|
set_bit(RTL8152_UNPLUG, &tp->flags);
|
||||||
|
|
||||||
tasklet_kill(&tp->tl);
|
tasklet_kill(&tp->tl);
|
||||||
unregister_netdev(tp->netdev);
|
unregister_netdev(tp->netdev);
|
||||||
tp->rtl_ops.unload(tp);
|
tp->rtl_ops.unload(tp);
|
||||||
|
|
|
@ -138,6 +138,9 @@ int __of_add_property_sysfs(struct device_node *np, struct property *pp)
|
||||||
/* Important: Don't leak passwords */
|
/* Important: Don't leak passwords */
|
||||||
bool secure = strncmp(pp->name, "security-", 9) == 0;
|
bool secure = strncmp(pp->name, "security-", 9) == 0;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!of_kset || !of_node_is_attached(np))
|
if (!of_kset || !of_node_is_attached(np))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -158,6 +161,9 @@ int __of_attach_node_sysfs(struct device_node *np)
|
||||||
struct property *pp;
|
struct property *pp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!of_kset)
|
if (!of_kset)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1713,6 +1719,9 @@ int __of_remove_property(struct device_node *np, struct property *prop)
|
||||||
|
|
||||||
void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
|
void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
|
||||||
{
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||||
|
return;
|
||||||
|
|
||||||
/* at early boot, bail here and defer setup to of_init() */
|
/* at early boot, bail here and defer setup to of_init() */
|
||||||
if (of_kset && of_node_is_attached(np))
|
if (of_kset && of_node_is_attached(np))
|
||||||
sysfs_remove_bin_file(&np->kobj, &prop->attr);
|
sysfs_remove_bin_file(&np->kobj, &prop->attr);
|
||||||
|
@ -1777,6 +1786,9 @@ int __of_update_property(struct device_node *np, struct property *newprop,
|
||||||
void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
|
void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
|
||||||
struct property *oldprop)
|
struct property *oldprop)
|
||||||
{
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||||
|
return;
|
||||||
|
|
||||||
/* At early boot, bail out and defer setup to of_init() */
|
/* At early boot, bail out and defer setup to of_init() */
|
||||||
if (!of_kset)
|
if (!of_kset)
|
||||||
return;
|
return;
|
||||||
|
@ -1847,6 +1859,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
|
||||||
{
|
{
|
||||||
struct property *pp;
|
struct property *pp;
|
||||||
|
|
||||||
|
of_aliases = of_find_node_by_path("/aliases");
|
||||||
of_chosen = of_find_node_by_path("/chosen");
|
of_chosen = of_find_node_by_path("/chosen");
|
||||||
if (of_chosen == NULL)
|
if (of_chosen == NULL)
|
||||||
of_chosen = of_find_node_by_path("/chosen@0");
|
of_chosen = of_find_node_by_path("/chosen@0");
|
||||||
|
@ -1862,7 +1875,6 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
|
||||||
of_stdout = of_find_node_by_path(name);
|
of_stdout = of_find_node_by_path(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
of_aliases = of_find_node_by_path("/aliases");
|
|
||||||
if (!of_aliases)
|
if (!of_aliases)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1986,7 +1998,7 @@ bool of_console_check(struct device_node *dn, char *name, int index)
|
||||||
{
|
{
|
||||||
if (!dn || dn != of_stdout || console_set_on_cmdline)
|
if (!dn || dn != of_stdout || console_set_on_cmdline)
|
||||||
return false;
|
return false;
|
||||||
return add_preferred_console(name, index, NULL);
|
return !add_preferred_console(name, index, NULL);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(of_console_check);
|
EXPORT_SYMBOL_GPL(of_console_check);
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,9 @@ void __of_detach_node_sysfs(struct device_node *np)
|
||||||
{
|
{
|
||||||
struct property *pp;
|
struct property *pp;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||||
|
return;
|
||||||
|
|
||||||
BUG_ON(!of_node_is_initialized(np));
|
BUG_ON(!of_node_is_initialized(np));
|
||||||
if (!of_kset)
|
if (!of_kset)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -928,7 +928,11 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
||||||
void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
|
void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
|
||||||
{
|
{
|
||||||
const u64 phys_offset = __pa(PAGE_OFFSET);
|
const u64 phys_offset = __pa(PAGE_OFFSET);
|
||||||
base &= PAGE_MASK;
|
|
||||||
|
if (!PAGE_ALIGNED(base)) {
|
||||||
|
size -= PAGE_SIZE - (base & ~PAGE_MASK);
|
||||||
|
base = PAGE_ALIGN(base);
|
||||||
|
}
|
||||||
size &= PAGE_MASK;
|
size &= PAGE_MASK;
|
||||||
|
|
||||||
if (base > MAX_PHYS_ADDR) {
|
if (base > MAX_PHYS_ADDR) {
|
||||||
|
@ -937,10 +941,10 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base + size > MAX_PHYS_ADDR) {
|
if (base + size - 1 > MAX_PHYS_ADDR) {
|
||||||
pr_warning("Ignoring memory range 0x%lx - 0x%llx\n",
|
pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
|
||||||
ULONG_MAX, base + size);
|
((u64)MAX_PHYS_ADDR) + 1, base + size);
|
||||||
size = MAX_PHYS_ADDR - base;
|
size = MAX_PHYS_ADDR - base + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base + size < phys_offset) {
|
if (base + size < phys_offset) {
|
||||||
|
|
|
@ -232,6 +232,7 @@ static struct platform_driver efi_rtc_driver = {
|
||||||
|
|
||||||
module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
|
module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
|
||||||
|
|
||||||
|
MODULE_ALIAS("platform:rtc-efi");
|
||||||
MODULE_AUTHOR("dann frazier <dannf@hp.com>");
|
MODULE_AUTHOR("dann frazier <dannf@hp.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_DESCRIPTION("EFI RTC driver");
|
MODULE_DESCRIPTION("EFI RTC driver");
|
||||||
|
|
|
@ -22,44 +22,63 @@
|
||||||
#define GSBI_CTRL_REG 0x0000
|
#define GSBI_CTRL_REG 0x0000
|
||||||
#define GSBI_PROTOCOL_SHIFT 4
|
#define GSBI_PROTOCOL_SHIFT 4
|
||||||
|
|
||||||
|
struct gsbi_info {
|
||||||
|
struct clk *hclk;
|
||||||
|
u32 mode;
|
||||||
|
u32 crci;
|
||||||
|
};
|
||||||
|
|
||||||
static int gsbi_probe(struct platform_device *pdev)
|
static int gsbi_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *node = pdev->dev.of_node;
|
struct device_node *node = pdev->dev.of_node;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
struct clk *hclk;
|
struct gsbi_info *gsbi;
|
||||||
u32 mode, crci = 0;
|
|
||||||
|
gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL);
|
||||||
|
|
||||||
|
if (!gsbi)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
base = devm_ioremap_resource(&pdev->dev, res);
|
base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
if (IS_ERR(base))
|
if (IS_ERR(base))
|
||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
if (of_property_read_u32(node, "qcom,mode", &mode)) {
|
if (of_property_read_u32(node, "qcom,mode", &gsbi->mode)) {
|
||||||
dev_err(&pdev->dev, "missing mode configuration\n");
|
dev_err(&pdev->dev, "missing mode configuration\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not required, so default to 0 if not present */
|
/* not required, so default to 0 if not present */
|
||||||
of_property_read_u32(node, "qcom,crci", &crci);
|
of_property_read_u32(node, "qcom,crci", &gsbi->crci);
|
||||||
|
|
||||||
dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n", mode, crci);
|
dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n",
|
||||||
|
gsbi->mode, gsbi->crci);
|
||||||
|
gsbi->hclk = devm_clk_get(&pdev->dev, "iface");
|
||||||
|
if (IS_ERR(gsbi->hclk))
|
||||||
|
return PTR_ERR(gsbi->hclk);
|
||||||
|
|
||||||
hclk = devm_clk_get(&pdev->dev, "iface");
|
clk_prepare_enable(gsbi->hclk);
|
||||||
if (IS_ERR(hclk))
|
|
||||||
return PTR_ERR(hclk);
|
|
||||||
|
|
||||||
clk_prepare_enable(hclk);
|
writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci,
|
||||||
|
|
||||||
writel_relaxed((mode << GSBI_PROTOCOL_SHIFT) | crci,
|
|
||||||
base + GSBI_CTRL_REG);
|
base + GSBI_CTRL_REG);
|
||||||
|
|
||||||
/* make sure the gsbi control write is not reordered */
|
/* make sure the gsbi control write is not reordered */
|
||||||
wmb();
|
wmb();
|
||||||
|
|
||||||
clk_disable_unprepare(hclk);
|
platform_set_drvdata(pdev, gsbi);
|
||||||
|
|
||||||
return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
|
return of_platform_populate(node, NULL, NULL, &pdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gsbi_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct gsbi_info *gsbi = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
clk_disable_unprepare(gsbi->hclk);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id gsbi_dt_match[] = {
|
static const struct of_device_id gsbi_dt_match[] = {
|
||||||
|
@ -76,6 +95,7 @@ static struct platform_driver gsbi_driver = {
|
||||||
.of_match_table = gsbi_dt_match,
|
.of_match_table = gsbi_dt_match,
|
||||||
},
|
},
|
||||||
.probe = gsbi_probe,
|
.probe = gsbi_probe,
|
||||||
|
.remove = gsbi_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(gsbi_driver);
|
module_platform_driver(gsbi_driver);
|
||||||
|
|
|
@ -50,18 +50,18 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
|
||||||
cache->brun_percent < 100);
|
cache->brun_percent < 100);
|
||||||
|
|
||||||
if (*args) {
|
if (*args) {
|
||||||
pr_err("'bind' command doesn't take an argument");
|
pr_err("'bind' command doesn't take an argument\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cache->rootdirname) {
|
if (!cache->rootdirname) {
|
||||||
pr_err("No cache directory specified");
|
pr_err("No cache directory specified\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't permit already bound caches to be re-bound */
|
/* don't permit already bound caches to be re-bound */
|
||||||
if (test_bit(CACHEFILES_READY, &cache->flags)) {
|
if (test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||||
pr_err("Cache already bound");
|
pr_err("Cache already bound\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ error_open_root:
|
||||||
kmem_cache_free(cachefiles_object_jar, fsdef);
|
kmem_cache_free(cachefiles_object_jar, fsdef);
|
||||||
error_root_object:
|
error_root_object:
|
||||||
cachefiles_end_secure(cache, saved_cred);
|
cachefiles_end_secure(cache, saved_cred);
|
||||||
pr_err("Failed to register: %d", ret);
|
pr_err("Failed to register: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ static unsigned int cachefiles_daemon_poll(struct file *file,
|
||||||
static int cachefiles_daemon_range_error(struct cachefiles_cache *cache,
|
static int cachefiles_daemon_range_error(struct cachefiles_cache *cache,
|
||||||
char *args)
|
char *args)
|
||||||
{
|
{
|
||||||
pr_err("Free space limits must be in range 0%%<=stop<cull<run<100%%");
|
pr_err("Free space limits must be in range 0%%<=stop<cull<run<100%%\n");
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -475,12 +475,12 @@ static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)
|
||||||
_enter(",%s", args);
|
_enter(",%s", args);
|
||||||
|
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
pr_err("Empty directory specified");
|
pr_err("Empty directory specified\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache->rootdirname) {
|
if (cache->rootdirname) {
|
||||||
pr_err("Second cache directory specified");
|
pr_err("Second cache directory specified\n");
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,12 +503,12 @@ static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
|
||||||
_enter(",%s", args);
|
_enter(",%s", args);
|
||||||
|
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
pr_err("Empty security context specified");
|
pr_err("Empty security context specified\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache->secctx) {
|
if (cache->secctx) {
|
||||||
pr_err("Second security context specified");
|
pr_err("Second security context specified\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +531,7 @@ static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args)
|
||||||
_enter(",%s", args);
|
_enter(",%s", args);
|
||||||
|
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
pr_err("Empty tag specified");
|
pr_err("Empty tag specified\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,12 +562,12 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
|
||||||
goto inval;
|
goto inval;
|
||||||
|
|
||||||
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||||
pr_err("cull applied to unready cache");
|
pr_err("cull applied to unready cache\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
||||||
pr_err("cull applied to dead cache");
|
pr_err("cull applied to dead cache\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,11 +587,11 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
|
||||||
|
|
||||||
notdir:
|
notdir:
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
pr_err("cull command requires dirfd to be a directory");
|
pr_err("cull command requires dirfd to be a directory\n");
|
||||||
return -ENOTDIR;
|
return -ENOTDIR;
|
||||||
|
|
||||||
inval:
|
inval:
|
||||||
pr_err("cull command requires dirfd and filename");
|
pr_err("cull command requires dirfd and filename\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,7 +614,7 @@ static int cachefiles_daemon_debug(struct cachefiles_cache *cache, char *args)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inval:
|
inval:
|
||||||
pr_err("debug command requires mask");
|
pr_err("debug command requires mask\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,12 +634,12 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
|
||||||
goto inval;
|
goto inval;
|
||||||
|
|
||||||
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||||
pr_err("inuse applied to unready cache");
|
pr_err("inuse applied to unready cache\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
||||||
pr_err("inuse applied to dead cache");
|
pr_err("inuse applied to dead cache\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,11 +659,11 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
|
||||||
|
|
||||||
notdir:
|
notdir:
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
pr_err("inuse command requires dirfd to be a directory");
|
pr_err("inuse command requires dirfd to be a directory\n");
|
||||||
return -ENOTDIR;
|
return -ENOTDIR;
|
||||||
|
|
||||||
inval:
|
inval:
|
||||||
pr_err("inuse command requires dirfd and filename");
|
pr_err("inuse command requires dirfd and filename\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,7 +255,7 @@ extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
|
||||||
|
|
||||||
#define cachefiles_io_error(___cache, FMT, ...) \
|
#define cachefiles_io_error(___cache, FMT, ...) \
|
||||||
do { \
|
do { \
|
||||||
pr_err("I/O Error: " FMT, ##__VA_ARGS__); \
|
pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__); \
|
||||||
fscache_io_error(&(___cache)->cache); \
|
fscache_io_error(&(___cache)->cache); \
|
||||||
set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
|
set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
@ -84,7 +84,7 @@ error_proc:
|
||||||
error_object_jar:
|
error_object_jar:
|
||||||
misc_deregister(&cachefiles_dev);
|
misc_deregister(&cachefiles_dev);
|
||||||
error_dev:
|
error_dev:
|
||||||
pr_err("failed to register: %d", ret);
|
pr_err("failed to register: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -543,7 +543,7 @@ lookup_again:
|
||||||
next, next->d_inode, next->d_inode->i_ino);
|
next, next->d_inode, next->d_inode->i_ino);
|
||||||
|
|
||||||
} else if (!S_ISDIR(next->d_inode->i_mode)) {
|
} else if (!S_ISDIR(next->d_inode->i_mode)) {
|
||||||
pr_err("inode %lu is not a directory",
|
pr_err("inode %lu is not a directory\n",
|
||||||
next->d_inode->i_ino);
|
next->d_inode->i_ino);
|
||||||
ret = -ENOBUFS;
|
ret = -ENOBUFS;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -574,7 +574,7 @@ lookup_again:
|
||||||
} else if (!S_ISDIR(next->d_inode->i_mode) &&
|
} else if (!S_ISDIR(next->d_inode->i_mode) &&
|
||||||
!S_ISREG(next->d_inode->i_mode)
|
!S_ISREG(next->d_inode->i_mode)
|
||||||
) {
|
) {
|
||||||
pr_err("inode %lu is not a file or directory",
|
pr_err("inode %lu is not a file or directory\n",
|
||||||
next->d_inode->i_ino);
|
next->d_inode->i_ino);
|
||||||
ret = -ENOBUFS;
|
ret = -ENOBUFS;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -768,7 +768,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
ASSERT(subdir->d_inode);
|
ASSERT(subdir->d_inode);
|
||||||
|
|
||||||
if (!S_ISDIR(subdir->d_inode->i_mode)) {
|
if (!S_ISDIR(subdir->d_inode->i_mode)) {
|
||||||
pr_err("%s is not a directory", dirname);
|
pr_err("%s is not a directory\n", dirname);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto check_error;
|
goto check_error;
|
||||||
}
|
}
|
||||||
|
@ -796,13 +796,13 @@ check_error:
|
||||||
mkdir_error:
|
mkdir_error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&dir->d_inode->i_mutex);
|
||||||
dput(subdir);
|
dput(subdir);
|
||||||
pr_err("mkdir %s failed with error %d", dirname, ret);
|
pr_err("mkdir %s failed with error %d\n", dirname, ret);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
lookup_error:
|
lookup_error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&dir->d_inode->i_mutex);
|
||||||
ret = PTR_ERR(subdir);
|
ret = PTR_ERR(subdir);
|
||||||
pr_err("Lookup %s failed with error %d", dirname, ret);
|
pr_err("Lookup %s failed with error %d\n", dirname, ret);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
nomem_d_alloc:
|
nomem_d_alloc:
|
||||||
|
@ -892,7 +892,7 @@ lookup_error:
|
||||||
if (ret == -EIO) {
|
if (ret == -EIO) {
|
||||||
cachefiles_io_error(cache, "Lookup failed");
|
cachefiles_io_error(cache, "Lookup failed");
|
||||||
} else if (ret != -ENOMEM) {
|
} else if (ret != -ENOMEM) {
|
||||||
pr_err("Internal error: %d", ret);
|
pr_err("Internal error: %d\n", ret);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +951,7 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != -ENOMEM) {
|
if (ret != -ENOMEM) {
|
||||||
pr_err("Internal error: %d", ret);
|
pr_err("Internal error: %d\n", ret);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != -EEXIST) {
|
if (ret != -EEXIST) {
|
||||||
pr_err("Can't set xattr on %*.*s [%lu] (err %d)",
|
pr_err("Can't set xattr on %*.*s [%lu] (err %d)\n",
|
||||||
dentry->d_name.len, dentry->d_name.len,
|
dentry->d_name.len, dentry->d_name.len,
|
||||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||||
-ret);
|
-ret);
|
||||||
|
@ -64,7 +64,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
|
||||||
if (ret == -ERANGE)
|
if (ret == -ERANGE)
|
||||||
goto bad_type_length;
|
goto bad_type_length;
|
||||||
|
|
||||||
pr_err("Can't read xattr on %*.*s [%lu] (err %d)",
|
pr_err("Can't read xattr on %*.*s [%lu] (err %d)\n",
|
||||||
dentry->d_name.len, dentry->d_name.len,
|
dentry->d_name.len, dentry->d_name.len,
|
||||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||||
-ret);
|
-ret);
|
||||||
|
@ -85,14 +85,14 @@ error:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bad_type_length:
|
bad_type_length:
|
||||||
pr_err("Cache object %lu type xattr length incorrect",
|
pr_err("Cache object %lu type xattr length incorrect\n",
|
||||||
dentry->d_inode->i_ino);
|
dentry->d_inode->i_ino);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
bad_type:
|
bad_type:
|
||||||
xtype[2] = 0;
|
xtype[2] = 0;
|
||||||
pr_err("Cache object %*.*s [%lu] type %s not %s",
|
pr_err("Cache object %*.*s [%lu] type %s not %s\n",
|
||||||
dentry->d_name.len, dentry->d_name.len,
|
dentry->d_name.len, dentry->d_name.len,
|
||||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||||
xtype, type);
|
xtype, type);
|
||||||
|
@ -293,7 +293,7 @@ error:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bad_type_length:
|
bad_type_length:
|
||||||
pr_err("Cache object %lu xattr length incorrect",
|
pr_err("Cache object %lu xattr length incorrect\n",
|
||||||
dentry->d_inode->i_ino);
|
dentry->d_inode->i_ino);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto error;
|
goto error;
|
||||||
|
|
112
fs/dcache.c
112
fs/dcache.c
|
@ -2372,7 +2372,8 @@ void dentry_update_name_case(struct dentry *dentry, struct qstr *name)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dentry_update_name_case);
|
EXPORT_SYMBOL(dentry_update_name_case);
|
||||||
|
|
||||||
static void switch_names(struct dentry *dentry, struct dentry *target)
|
static void switch_names(struct dentry *dentry, struct dentry *target,
|
||||||
|
bool exchange)
|
||||||
{
|
{
|
||||||
if (dname_external(target)) {
|
if (dname_external(target)) {
|
||||||
if (dname_external(dentry)) {
|
if (dname_external(dentry)) {
|
||||||
|
@ -2406,13 +2407,19 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
|
||||||
*/
|
*/
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long)));
|
BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long)));
|
||||||
|
if (!exchange) {
|
||||||
|
memcpy(dentry->d_iname, target->d_name.name,
|
||||||
|
target->d_name.len + 1);
|
||||||
|
dentry->d_name.hash_len = target->d_name.hash_len;
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) {
|
for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) {
|
||||||
swap(((long *) &dentry->d_iname)[i],
|
swap(((long *) &dentry->d_iname)[i],
|
||||||
((long *) &target->d_iname)[i]);
|
((long *) &target->d_iname)[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
swap(dentry->d_name.len, target->d_name.len);
|
swap(dentry->d_name.hash_len, target->d_name.hash_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
|
static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
|
||||||
|
@ -2442,25 +2449,29 @@ static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dentry_unlock_parents_for_move(struct dentry *dentry,
|
static void dentry_unlock_for_move(struct dentry *dentry, struct dentry *target)
|
||||||
struct dentry *target)
|
|
||||||
{
|
{
|
||||||
if (target->d_parent != dentry->d_parent)
|
if (target->d_parent != dentry->d_parent)
|
||||||
spin_unlock(&dentry->d_parent->d_lock);
|
spin_unlock(&dentry->d_parent->d_lock);
|
||||||
if (target->d_parent != target)
|
if (target->d_parent != target)
|
||||||
spin_unlock(&target->d_parent->d_lock);
|
spin_unlock(&target->d_parent->d_lock);
|
||||||
|
spin_unlock(&target->d_lock);
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When switching names, the actual string doesn't strictly have to
|
* When switching names, the actual string doesn't strictly have to
|
||||||
* be preserved in the target - because we're dropping the target
|
* be preserved in the target - because we're dropping the target
|
||||||
* anyway. As such, we can just do a simple memcpy() to copy over
|
* anyway. As such, we can just do a simple memcpy() to copy over
|
||||||
* the new name before we switch.
|
* the new name before we switch, unless we are going to rehash
|
||||||
*
|
* it. Note that if we *do* unhash the target, we are not allowed
|
||||||
* Note that we have to be a lot more careful about getting the hash
|
* to rehash it without giving it a new name/hash key - whether
|
||||||
* switched - we have to switch the hash value properly even if it
|
* we swap or overwrite the names here, resulting name won't match
|
||||||
* then no longer matches the actual (corrupted) string of the target.
|
* the reality in filesystem; it's only there for d_path() purposes.
|
||||||
* The hash value has to match the hash queue that the dentry is on..
|
* Note that all of this is happening under rename_lock, so the
|
||||||
|
* any hash lookup seeing it in the middle of manipulations will
|
||||||
|
* be discarded anyway. So we do not care what happens to the hash
|
||||||
|
* key in that case.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* __d_move - move a dentry
|
* __d_move - move a dentry
|
||||||
|
@ -2506,36 +2517,30 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
|
||||||
d_hash(dentry->d_parent, dentry->d_name.hash));
|
d_hash(dentry->d_parent, dentry->d_name.hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&dentry->d_u.d_child);
|
|
||||||
list_del(&target->d_u.d_child);
|
|
||||||
|
|
||||||
/* Switch the names.. */
|
/* Switch the names.. */
|
||||||
switch_names(dentry, target);
|
switch_names(dentry, target, exchange);
|
||||||
swap(dentry->d_name.hash, target->d_name.hash);
|
|
||||||
|
|
||||||
/* ... and switch the parents */
|
/* ... and switch them in the tree */
|
||||||
if (IS_ROOT(dentry)) {
|
if (IS_ROOT(dentry)) {
|
||||||
|
/* splicing a tree */
|
||||||
dentry->d_parent = target->d_parent;
|
dentry->d_parent = target->d_parent;
|
||||||
target->d_parent = target;
|
target->d_parent = target;
|
||||||
INIT_LIST_HEAD(&target->d_u.d_child);
|
list_del_init(&target->d_u.d_child);
|
||||||
|
list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
|
||||||
} else {
|
} else {
|
||||||
|
/* swapping two dentries */
|
||||||
swap(dentry->d_parent, target->d_parent);
|
swap(dentry->d_parent, target->d_parent);
|
||||||
|
list_move(&target->d_u.d_child, &target->d_parent->d_subdirs);
|
||||||
/* And add them back to the (new) parent lists */
|
list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
|
||||||
list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
|
if (exchange)
|
||||||
|
fsnotify_d_move(target);
|
||||||
|
fsnotify_d_move(dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
|
|
||||||
|
|
||||||
write_seqcount_end(&target->d_seq);
|
write_seqcount_end(&target->d_seq);
|
||||||
write_seqcount_end(&dentry->d_seq);
|
write_seqcount_end(&dentry->d_seq);
|
||||||
|
|
||||||
dentry_unlock_parents_for_move(dentry, target);
|
dentry_unlock_for_move(dentry, target);
|
||||||
if (exchange)
|
|
||||||
fsnotify_d_move(target);
|
|
||||||
spin_unlock(&target->d_lock);
|
|
||||||
fsnotify_d_move(dentry);
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2633,45 +2638,6 @@ out_err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Prepare an anonymous dentry for life in the superblock's dentry tree as a
|
|
||||||
* named dentry in place of the dentry to be replaced.
|
|
||||||
* returns with anon->d_lock held!
|
|
||||||
*/
|
|
||||||
static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
|
|
||||||
{
|
|
||||||
struct dentry *dparent;
|
|
||||||
|
|
||||||
dentry_lock_for_move(anon, dentry);
|
|
||||||
|
|
||||||
write_seqcount_begin(&dentry->d_seq);
|
|
||||||
write_seqcount_begin_nested(&anon->d_seq, DENTRY_D_LOCK_NESTED);
|
|
||||||
|
|
||||||
dparent = dentry->d_parent;
|
|
||||||
|
|
||||||
switch_names(dentry, anon);
|
|
||||||
swap(dentry->d_name.hash, anon->d_name.hash);
|
|
||||||
|
|
||||||
dentry->d_parent = dentry;
|
|
||||||
list_del_init(&dentry->d_u.d_child);
|
|
||||||
anon->d_parent = dparent;
|
|
||||||
if (likely(!d_unhashed(anon))) {
|
|
||||||
hlist_bl_lock(&anon->d_sb->s_anon);
|
|
||||||
__hlist_bl_del(&anon->d_hash);
|
|
||||||
anon->d_hash.pprev = NULL;
|
|
||||||
hlist_bl_unlock(&anon->d_sb->s_anon);
|
|
||||||
}
|
|
||||||
list_move(&anon->d_u.d_child, &dparent->d_subdirs);
|
|
||||||
|
|
||||||
write_seqcount_end(&dentry->d_seq);
|
|
||||||
write_seqcount_end(&anon->d_seq);
|
|
||||||
|
|
||||||
dentry_unlock_parents_for_move(anon, dentry);
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
|
|
||||||
/* anon->d_lock still locked, returns locked */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* d_splice_alias - splice a disconnected dentry into the tree if one exists
|
* d_splice_alias - splice a disconnected dentry into the tree if one exists
|
||||||
* @inode: the inode which may have a disconnected dentry
|
* @inode: the inode which may have a disconnected dentry
|
||||||
|
@ -2717,10 +2683,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
|
||||||
return ERR_PTR(-EIO);
|
return ERR_PTR(-EIO);
|
||||||
}
|
}
|
||||||
write_seqlock(&rename_lock);
|
write_seqlock(&rename_lock);
|
||||||
__d_materialise_dentry(dentry, new);
|
__d_move(new, dentry, false);
|
||||||
write_sequnlock(&rename_lock);
|
write_sequnlock(&rename_lock);
|
||||||
_d_rehash(new);
|
|
||||||
spin_unlock(&new->d_lock);
|
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
security_d_instantiate(new, inode);
|
security_d_instantiate(new, inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
|
@ -2780,7 +2744,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
|
||||||
} else if (IS_ROOT(alias)) {
|
} else if (IS_ROOT(alias)) {
|
||||||
/* Is this an anonymous mountpoint that we
|
/* Is this an anonymous mountpoint that we
|
||||||
* could splice into our tree? */
|
* could splice into our tree? */
|
||||||
__d_materialise_dentry(dentry, alias);
|
__d_move(alias, dentry, false);
|
||||||
write_sequnlock(&rename_lock);
|
write_sequnlock(&rename_lock);
|
||||||
goto found;
|
goto found;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2807,13 +2771,9 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
|
||||||
actual = __d_instantiate_unique(dentry, inode);
|
actual = __d_instantiate_unique(dentry, inode);
|
||||||
if (!actual)
|
if (!actual)
|
||||||
actual = dentry;
|
actual = dentry;
|
||||||
else
|
|
||||||
BUG_ON(!d_unhashed(actual));
|
|
||||||
|
|
||||||
spin_lock(&actual->d_lock);
|
d_rehash(actual);
|
||||||
found:
|
found:
|
||||||
_d_rehash(actual);
|
|
||||||
spin_unlock(&actual->d_lock);
|
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
out_nolock:
|
out_nolock:
|
||||||
if (actual == dentry) {
|
if (actual == dentry) {
|
||||||
|
|
|
@ -158,7 +158,7 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret = iov_iter_get_pages(sdio->iter, dio->pages, DIO_PAGES,
|
ret = iov_iter_get_pages(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES,
|
||||||
&sdio->from);
|
&sdio->from);
|
||||||
|
|
||||||
if (ret < 0 && sdio->blocks_available && (dio->rw & WRITE)) {
|
if (ret < 0 && sdio->blocks_available && (dio->rw & WRITE)) {
|
||||||
|
|
|
@ -1305,6 +1305,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
|
||||||
size_t start;
|
size_t start;
|
||||||
ssize_t ret = iov_iter_get_pages(ii,
|
ssize_t ret = iov_iter_get_pages(ii,
|
||||||
&req->pages[req->num_pages],
|
&req->pages[req->num_pages],
|
||||||
|
*nbytesp - nbytes,
|
||||||
req->max_pages - req->num_pages,
|
req->max_pages - req->num_pages,
|
||||||
&start);
|
&start);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -3104,7 +3104,8 @@ static __be32 nfsd4_encode_splice_read(
|
||||||
|
|
||||||
buf->page_len = maxcount;
|
buf->page_len = maxcount;
|
||||||
buf->len += maxcount;
|
buf->len += maxcount;
|
||||||
xdr->page_ptr += (maxcount + PAGE_SIZE - 1) / PAGE_SIZE;
|
xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1)
|
||||||
|
/ PAGE_SIZE;
|
||||||
|
|
||||||
/* Use rest of head for padding and remaining ops: */
|
/* Use rest of head for padding and remaining ops: */
|
||||||
buf->tail[0].iov_base = xdr->p;
|
buf->tail[0].iov_base = xdr->p;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/gfp.h>
|
#include <linux/gfp.h>
|
||||||
#include <linux/mpage.h>
|
#include <linux/mpage.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/aio.h>
|
#include <linux/aio.h>
|
||||||
#include "nilfs.h"
|
#include "nilfs.h"
|
||||||
|
@ -219,10 +220,10 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc)
|
||||||
|
|
||||||
static int nilfs_set_page_dirty(struct page *page)
|
static int nilfs_set_page_dirty(struct page *page)
|
||||||
{
|
{
|
||||||
|
struct inode *inode = page->mapping->host;
|
||||||
int ret = __set_page_dirty_nobuffers(page);
|
int ret = __set_page_dirty_nobuffers(page);
|
||||||
|
|
||||||
if (page_has_buffers(page)) {
|
if (page_has_buffers(page)) {
|
||||||
struct inode *inode = page->mapping->host;
|
|
||||||
unsigned nr_dirty = 0;
|
unsigned nr_dirty = 0;
|
||||||
struct buffer_head *bh, *head;
|
struct buffer_head *bh, *head;
|
||||||
|
|
||||||
|
@ -245,6 +246,10 @@ static int nilfs_set_page_dirty(struct page *page)
|
||||||
|
|
||||||
if (nr_dirty)
|
if (nr_dirty)
|
||||||
nilfs_set_file_dirty(inode, nr_dirty);
|
nilfs_set_file_dirty(inode, nr_dirty);
|
||||||
|
} else if (ret) {
|
||||||
|
unsigned nr_dirty = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
|
||||||
|
|
||||||
|
nilfs_set_file_dirty(inode, nr_dirty);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -655,12 +655,9 @@ void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm,
|
||||||
clear_bit(bit, res->refmap);
|
clear_bit(bit, res->refmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
||||||
void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
|
||||||
struct dlm_lock_resource *res)
|
struct dlm_lock_resource *res)
|
||||||
{
|
{
|
||||||
assert_spin_locked(&res->spinlock);
|
|
||||||
|
|
||||||
res->inflight_locks++;
|
res->inflight_locks++;
|
||||||
|
|
||||||
mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name,
|
mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name,
|
||||||
|
@ -668,6 +665,13 @@ void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
||||||
__builtin_return_address(0));
|
__builtin_return_address(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
||||||
|
struct dlm_lock_resource *res)
|
||||||
|
{
|
||||||
|
assert_spin_locked(&res->spinlock);
|
||||||
|
__dlm_lockres_grab_inflight_ref(dlm, res);
|
||||||
|
}
|
||||||
|
|
||||||
void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
|
void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
|
||||||
struct dlm_lock_resource *res)
|
struct dlm_lock_resource *res)
|
||||||
{
|
{
|
||||||
|
@ -894,10 +898,8 @@ lookup:
|
||||||
/* finally add the lockres to its hash bucket */
|
/* finally add the lockres to its hash bucket */
|
||||||
__dlm_insert_lockres(dlm, res);
|
__dlm_insert_lockres(dlm, res);
|
||||||
|
|
||||||
/* Grab inflight ref to pin the resource */
|
/* since this lockres is new it doesn't not require the spinlock */
|
||||||
spin_lock(&res->spinlock);
|
__dlm_lockres_grab_inflight_ref(dlm, res);
|
||||||
dlm_lockres_grab_inflight_ref(dlm, res);
|
|
||||||
spin_unlock(&res->spinlock);
|
|
||||||
|
|
||||||
/* get an extra ref on the mle in case this is a BLOCK
|
/* get an extra ref on the mle in case this is a BLOCK
|
||||||
* if so, the creator of the BLOCK may try to put the last
|
* if so, the creator of the BLOCK may try to put the last
|
||||||
|
|
|
@ -2532,6 +2532,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb)
|
||||||
kfree(osb->journal);
|
kfree(osb->journal);
|
||||||
kfree(osb->local_alloc_copy);
|
kfree(osb->local_alloc_copy);
|
||||||
kfree(osb->uuid_str);
|
kfree(osb->uuid_str);
|
||||||
|
kfree(osb->vol_label);
|
||||||
ocfs2_put_dlm_debug(osb->osb_dlm_debug);
|
ocfs2_put_dlm_debug(osb->osb_dlm_debug);
|
||||||
memset(osb, 0, sizeof(struct ocfs2_super));
|
memset(osb, 0, sizeof(struct ocfs2_super));
|
||||||
}
|
}
|
||||||
|
|
|
@ -931,23 +931,32 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
|
||||||
while (addr < end) {
|
while (addr < end) {
|
||||||
struct vm_area_struct *vma = find_vma(walk->mm, addr);
|
struct vm_area_struct *vma = find_vma(walk->mm, addr);
|
||||||
pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
|
pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
|
||||||
unsigned long vm_end;
|
/* End of address space hole, which we mark as non-present. */
|
||||||
|
unsigned long hole_end;
|
||||||
|
|
||||||
if (!vma) {
|
if (vma)
|
||||||
vm_end = end;
|
hole_end = min(end, vma->vm_start);
|
||||||
} else {
|
else
|
||||||
vm_end = min(end, vma->vm_end);
|
hole_end = end;
|
||||||
if (vma->vm_flags & VM_SOFTDIRTY)
|
|
||||||
pme.pme |= PM_STATUS2(pm->v2, __PM_SOFT_DIRTY);
|
for (; addr < hole_end; addr += PAGE_SIZE) {
|
||||||
|
err = add_to_pagemap(addr, &pme, pm);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; addr < vm_end; addr += PAGE_SIZE) {
|
if (!vma)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Addresses in the VMA. */
|
||||||
|
if (vma->vm_flags & VM_SOFTDIRTY)
|
||||||
|
pme.pme |= PM_STATUS2(pm->v2, __PM_SOFT_DIRTY);
|
||||||
|
for (; addr < min(end, vma->vm_end); addr += PAGE_SIZE) {
|
||||||
err = add_to_pagemap(addr, &pme, pm);
|
err = add_to_pagemap(addr, &pme, pm);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,7 +298,10 @@ cg_found:
|
||||||
ufsi->i_oeftflag = 0;
|
ufsi->i_oeftflag = 0;
|
||||||
ufsi->i_dir_start_lookup = 0;
|
ufsi->i_dir_start_lookup = 0;
|
||||||
memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
|
memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
|
||||||
insert_inode_hash(inode);
|
if (insert_inode_locked(inode) < 0) {
|
||||||
|
err = -EIO;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
|
|
||||||
if (uspi->fs_magic == UFS2_MAGIC) {
|
if (uspi->fs_magic == UFS2_MAGIC) {
|
||||||
|
@ -337,6 +340,7 @@ cg_found:
|
||||||
fail_remove_inode:
|
fail_remove_inode:
|
||||||
unlock_ufs(sb);
|
unlock_ufs(sb);
|
||||||
clear_nlink(inode);
|
clear_nlink(inode);
|
||||||
|
unlock_new_inode(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
UFSD("EXIT (FAILED): err %d\n", err);
|
UFSD("EXIT (FAILED): err %d\n", err);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
|
@ -38,10 +38,12 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
|
||||||
{
|
{
|
||||||
int err = ufs_add_link(dentry, inode);
|
int err = ufs_add_link(dentry, inode);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
unlock_new_inode(inode);
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
|
unlock_new_inode(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +157,7 @@ out_notlocked:
|
||||||
|
|
||||||
out_fail:
|
out_fail:
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
|
unlock_new_inode(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +213,7 @@ out:
|
||||||
out_fail:
|
out_fail:
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
|
unlock_new_inode(inode);
|
||||||
iput (inode);
|
iput (inode);
|
||||||
inode_dec_link_count(dir);
|
inode_dec_link_count(dir);
|
||||||
unlock_ufs(dir->i_sb);
|
unlock_ufs(dir->i_sb);
|
||||||
|
|
|
@ -118,6 +118,7 @@ struct acpi_device;
|
||||||
struct acpi_hotplug_profile {
|
struct acpi_hotplug_profile {
|
||||||
struct kobject kobj;
|
struct kobject kobj;
|
||||||
int (*scan_dependent)(struct acpi_device *adev);
|
int (*scan_dependent)(struct acpi_device *adev);
|
||||||
|
void (*notify_online)(struct acpi_device *adev);
|
||||||
bool enabled:1;
|
bool enabled:1;
|
||||||
bool demand_offline:1;
|
bool demand_offline:1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,12 +93,12 @@ extern int cpuset_slab_spread_node(void);
|
||||||
|
|
||||||
static inline int cpuset_do_page_mem_spread(void)
|
static inline int cpuset_do_page_mem_spread(void)
|
||||||
{
|
{
|
||||||
return current->flags & PF_SPREAD_PAGE;
|
return task_spread_page(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cpuset_do_slab_mem_spread(void)
|
static inline int cpuset_do_slab_mem_spread(void)
|
||||||
{
|
{
|
||||||
return current->flags & PF_SPREAD_SLAB;
|
return task_spread_slab(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int current_cpuset_is_being_rebound(void);
|
extern int current_cpuset_is_being_rebound(void);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue