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:
Коммит
739e4a758e
|
@ -345,14 +345,14 @@ the named feature on.
|
|||
The implementation is simple.
|
||||
|
||||
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
|
||||
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()
|
||||
returns the node to prefer for the allocation.
|
||||
|
||||
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().
|
||||
|
||||
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>
|
||||
- port: A port node with endpoint definitions as defined in
|
||||
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
|
||||
to the four LVDS multiplexer inputs.
|
||||
|
||||
|
@ -78,6 +81,8 @@ ldb: ldb@53fa8008 {
|
|||
"di0", "di1";
|
||||
|
||||
lvds-channel@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
fsl,data-mapping = "spwg";
|
||||
fsl,data-width = <24>;
|
||||
|
@ -86,7 +91,9 @@ ldb: ldb@53fa8008 {
|
|||
/* ... */
|
||||
};
|
||||
|
||||
port {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
lvds0_in: endpoint {
|
||||
remote-endpoint = <&ipu_di0_lvds0>;
|
||||
};
|
||||
|
@ -94,6 +101,8 @@ ldb: ldb@53fa8008 {
|
|||
};
|
||||
|
||||
lvds-channel@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
fsl,data-mapping = "spwg";
|
||||
fsl,data-width = <24>;
|
||||
|
@ -102,7 +111,9 @@ ldb: ldb@53fa8008 {
|
|||
/* ... */
|
||||
};
|
||||
|
||||
port {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lvds1_in: endpoint {
|
||||
remote-endpoint = <&ipu_di1_lvds1>;
|
||||
};
|
||||
|
|
|
@ -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/
|
||||
|
||||
BROCADE BNA 10 GIGABIT ETHERNET DRIVER
|
||||
M: Rasesh Mody <rmody@brocade.com>
|
||||
M: Rasesh Mody <rasesh.mody@qlogic.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/brocade/bna/
|
||||
|
@ -3012,9 +3012,8 @@ S: Supported
|
|||
F: drivers/acpi/dock.c
|
||||
|
||||
DOCUMENTATION
|
||||
M: Randy Dunlap <rdunlap@infradead.org>
|
||||
M: Jiri Kosina <jkosina@suse.cz>
|
||||
L: linux-doc@vger.kernel.org
|
||||
T: quilt http://www.infradead.org/~rdunlap/Doc/patches/
|
||||
S: Maintained
|
||||
F: Documentation/
|
||||
X: Documentation/ABI/
|
||||
|
@ -4477,7 +4476,6 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com>
|
|||
L: linux-i2c@vger.kernel.org
|
||||
L: linux-acpi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/i2c/i2c-acpi.c
|
||||
|
||||
I2C-TAOS-EVM DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.de>
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 17
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Shuffling Zombie Juror
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -447,22 +447,19 @@
|
|||
gpmc,device-width = <2>;
|
||||
gpmc,sync-clk-ps = <0>;
|
||||
gpmc,cs-on-ns = <0>;
|
||||
gpmc,cs-rd-off-ns = <40>;
|
||||
gpmc,cs-wr-off-ns = <40>;
|
||||
gpmc,cs-rd-off-ns = <80>;
|
||||
gpmc,cs-wr-off-ns = <80>;
|
||||
gpmc,adv-on-ns = <0>;
|
||||
gpmc,adv-rd-off-ns = <30>;
|
||||
gpmc,adv-wr-off-ns = <30>;
|
||||
gpmc,we-on-ns = <5>;
|
||||
gpmc,we-off-ns = <25>;
|
||||
gpmc,oe-on-ns = <2>;
|
||||
gpmc,oe-off-ns = <20>;
|
||||
gpmc,access-ns = <20>;
|
||||
gpmc,wr-access-ns = <40>;
|
||||
gpmc,rd-cycle-ns = <40>;
|
||||
gpmc,wr-cycle-ns = <40>;
|
||||
gpmc,wait-pin = <0>;
|
||||
gpmc,wait-on-read;
|
||||
gpmc,wait-on-write;
|
||||
gpmc,adv-rd-off-ns = <60>;
|
||||
gpmc,adv-wr-off-ns = <60>;
|
||||
gpmc,we-on-ns = <10>;
|
||||
gpmc,we-off-ns = <50>;
|
||||
gpmc,oe-on-ns = <4>;
|
||||
gpmc,oe-off-ns = <40>;
|
||||
gpmc,access-ns = <40>;
|
||||
gpmc,wr-access-ns = <80>;
|
||||
gpmc,rd-cycle-ns = <80>;
|
||||
gpmc,wr-cycle-ns = <80>;
|
||||
gpmc,bus-turnaround-ns = <0>;
|
||||
gpmc,cycle2cycle-delay-ns = <0>;
|
||||
gpmc,clk-activation-ns = <0>;
|
||||
|
|
|
@ -423,10 +423,14 @@
|
|||
status = "disabled";
|
||||
|
||||
lvds-channel@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
status = "disabled";
|
||||
|
||||
port {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
lvds0_in: endpoint {
|
||||
remote-endpoint = <&ipu_di0_lvds0>;
|
||||
};
|
||||
|
@ -434,10 +438,14 @@
|
|||
};
|
||||
|
||||
lvds-channel@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
status = "disabled";
|
||||
|
||||
port {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lvds1_in: endpoint {
|
||||
remote-endpoint = <&ipu_di1_lvds1>;
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@ clocks {
|
|||
#clock-cells = <0>;
|
||||
compatible = "ti,keystone,psc-clock";
|
||||
clocks = <&chipclk16>;
|
||||
clock-output-names = "usb";
|
||||
clock-output-names = "usb1";
|
||||
reg = <0x02350004 0xb00>, <0x02350000 0x400>;
|
||||
reg-names = "control", "domain";
|
||||
domain-id = <0>;
|
||||
|
@ -60,8 +60,8 @@ clocks {
|
|||
#clock-cells = <0>;
|
||||
compatible = "ti,keystone,psc-clock";
|
||||
clocks = <&chipclk12>;
|
||||
clock-output-names = "pcie";
|
||||
reg = <0x0235006c 0xb00>, <0x02350000 0x400>;
|
||||
clock-output-names = "pcie1";
|
||||
reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
|
||||
reg-names = "control", "domain";
|
||||
domain-id = <18>;
|
||||
};
|
||||
|
|
|
@ -353,13 +353,12 @@
|
|||
};
|
||||
|
||||
ldo8_reg: ldo8 {
|
||||
/* VDD_3v0: Does not go anywhere */
|
||||
/* VDD_3V_GP: act led/serial console */
|
||||
regulator-name = "ldo8";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
/* Unused */
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
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) \
|
||||
asm volatile( \
|
||||
".arch armv7-a \n\t" \
|
||||
"stmfd sp!, {fp, ip} \n\t" \
|
||||
"mrc p15, 0, r0, c1, c0, 0 @ get SCTLR \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"
|
||||
: : "r" (val));
|
||||
} else {
|
||||
#ifdef CONFIG_KUSER_HELPERS
|
||||
/*
|
||||
* User space must never try to access this
|
||||
* directly. Expect your app to break
|
||||
|
@ -89,6 +90,7 @@ static inline void set_tls(unsigned long val)
|
|||
* entry-armv.S for details)
|
||||
*/
|
||||
*((unsigned int *)0xffff0ff0) = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -110,10 +110,13 @@
|
|||
*
|
||||
* @ TESTCASE_START
|
||||
* bl __kprobes_test_case_start
|
||||
* @ start of inline data...
|
||||
* .pushsection .rodata
|
||||
* "10:
|
||||
* .ascii "mov r0, r7" @ text title for test case
|
||||
* .byte 0
|
||||
* .align 2, 0
|
||||
* .popsection
|
||||
* @ start of inline data...
|
||||
* .word 10b @ pointer to title in .rodata section
|
||||
*
|
||||
* @ TEST_ARG_REG
|
||||
* .byte ARG_TYPE_REG
|
||||
|
@ -971,7 +974,7 @@ void __naked __kprobes_test_case_start(void)
|
|||
__asm__ __volatile__ (
|
||||
"stmdb sp!, {r4-r11} \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"
|
||||
"bl kprobes_test_case_start \n\t"
|
||||
"bx r0 \n\t"
|
||||
|
@ -1349,15 +1352,14 @@ static unsigned long next_instruction(unsigned long pc)
|
|||
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_end *end_arg;
|
||||
unsigned long test_code;
|
||||
|
||||
args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);
|
||||
|
||||
current_title = title;
|
||||
current_title = *title++;
|
||||
args = (struct test_arg *)title;
|
||||
current_args = args;
|
||||
current_stack = stack;
|
||||
|
||||
|
|
|
@ -111,11 +111,14 @@ struct test_arg_end {
|
|||
#define TESTCASE_START(title) \
|
||||
__asm__ __volatile__ ( \
|
||||
"bl __kprobes_test_case_start \n\t" \
|
||||
".pushsection .rodata \n\t" \
|
||||
"10: \n\t" \
|
||||
/* don't use .asciz here as 'title' may be */ \
|
||||
/* multiple strings to be concatenated. */ \
|
||||
".ascii "#title" \n\t" \
|
||||
".byte 0 \n\t" \
|
||||
".align 2, 0 \n\t"
|
||||
".popsection \n\t" \
|
||||
".word 10b \n\t"
|
||||
|
||||
#define TEST_ARG_REG(reg, val) \
|
||||
".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);
|
||||
|
||||
if (gate->share_count)
|
||||
return !!(*gate->share_count);
|
||||
return !!__clk_get_enable_count(hw->clk);
|
||||
else
|
||||
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->flags = clk_gate2_flags;
|
||||
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;
|
||||
|
||||
init.name = name;
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
menu "TI OMAP/AM/DM/DRA Family"
|
||||
depends on ARCH_MULTI_V6 || ARCH_MULTI_V7
|
||||
|
||||
config ARCH_OMAP
|
||||
bool
|
||||
|
||||
config ARCH_OMAP2
|
||||
bool "TI OMAP2"
|
||||
depends on ARCH_MULTI_V6
|
||||
|
|
|
@ -2065,7 +2065,7 @@ static void _reconfigure_io_chain(void)
|
|||
|
||||
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();
|
||||
else if (cpu_is_omap44xx())
|
||||
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,
|
||||
.save_and_clear_irqen = &omap3xxx_prm_save_and_clear_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
|
||||
* I/O wakeup gates are aligned with the current mux settings. Works
|
||||
* by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
|
||||
* 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;
|
||||
|
||||
|
@ -399,6 +414,15 @@ void omap3xxx_prm_reconfigure_io_chain(void)
|
|||
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
|
||||
*
|
||||
|
@ -656,6 +680,13 @@ static int omap3xxx_prm_late_init(void)
|
|||
if (!(prm_features & PRM_HAS_IO_WAKEUP))
|
||||
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();
|
||||
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
|
||||
if (!ret)
|
||||
|
|
|
@ -61,7 +61,7 @@ EXPORT_SYMBOL(get_clock_tick_rate);
|
|||
/*
|
||||
* 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),
|
||||
get_clock_tick_rate());
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
* This code is not portable to processors with late data abort handling.
|
||||
*/
|
||||
#define CODING_BITS(i) (i & 0x0e000000)
|
||||
#define COND_BITS(i) (i & 0xf0000000)
|
||||
|
||||
#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
|
||||
#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;
|
||||
|
||||
case 0x04000000: /* ldr or str immediate */
|
||||
if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */
|
||||
goto bad;
|
||||
offset.un = OFFSET_BITS(instr);
|
||||
handler = do_alignment_ldrstr;
|
||||
break;
|
||||
|
|
|
@ -157,9 +157,9 @@ ENDPROC(cpu_v7_set_pte_ext)
|
|||
* TFR EV X F IHD LR S
|
||||
* .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM
|
||||
* 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
|
||||
.type v7_crval, #object
|
||||
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
|
||||
|
||||
menu "TI OMAP Common Features"
|
||||
|
|
|
@ -129,7 +129,11 @@ NESTED(_mcount, PT_SIZE, ra)
|
|||
nop
|
||||
#endif
|
||||
b ftrace_stub
|
||||
#ifdef CONFIG_32BIT
|
||||
addiu sp, sp, 8
|
||||
#else
|
||||
nop
|
||||
#endif
|
||||
|
||||
static_trace:
|
||||
MCOUNT_SAVE_REGS
|
||||
|
@ -139,6 +143,9 @@ static_trace:
|
|||
move a1, AT /* arg2: parent's return address */
|
||||
|
||||
MCOUNT_RESTORE_REGS
|
||||
#ifdef CONFIG_32BIT
|
||||
addiu sp, sp, 8
|
||||
#endif
|
||||
.globl ftrace_stub
|
||||
ftrace_stub:
|
||||
RETURN_BACK
|
||||
|
@ -183,6 +190,11 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
|
|||
jal prepare_ftrace_return
|
||||
nop
|
||||
MCOUNT_RESTORE_REGS
|
||||
#ifndef CONFIG_DYNAMIC_FTRACE
|
||||
#ifdef CONFIG_32BIT
|
||||
addiu sp, sp, 8
|
||||
#endif
|
||||
#endif
|
||||
RETURN_BACK
|
||||
END(ftrace_graph_caller)
|
||||
|
||||
|
|
|
@ -650,9 +650,9 @@ static inline int cop1_64bit(struct pt_regs *xcp)
|
|||
#define SIFROMREG(si, x) \
|
||||
do { \
|
||||
if (cop1_64bit(xcp)) \
|
||||
(si) = get_fpr32(&ctx->fpr[x], 0); \
|
||||
(si) = (int)get_fpr32(&ctx->fpr[x], 0); \
|
||||
else \
|
||||
(si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \
|
||||
(si) = (int)get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \
|
||||
} while (0)
|
||||
|
||||
#define SITOREG(si, x) \
|
||||
|
@ -667,7 +667,7 @@ do { \
|
|||
} \
|
||||
} 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) \
|
||||
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
|
||||
|
||||
ifeq ($(CONFIG_EFI_STUB), y)
|
||||
VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
|
||||
$(objtree)/drivers/firmware/efi/libstub/lib.a
|
||||
VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
|
||||
endif
|
||||
|
||||
$(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)
|
||||
{
|
||||
int i;
|
||||
struct setup_data *ptr;
|
||||
|
||||
for (i = 0; i < MEM_AVOID_MAX; i++) {
|
||||
if (mem_overlaps(img, &mem_avoid[i]))
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
|
||||
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) \
|
||||
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);
|
||||
output_string = efi_early->text_output + offset;
|
||||
out = (typeof(out))(unsigned long)efi_early->text_output;
|
||||
func = (u64 *)output_string;
|
||||
|
||||
efi_early->call(*func, efi_early->text_output, str);
|
||||
efi_early->call(*func, out, str);
|
||||
} else {
|
||||
struct efi_simple_text_output_protocol_32 *out;
|
||||
u32 *func;
|
||||
|
||||
offset = offsetof(typeof(*out), output_string);
|
||||
output_string = efi_early->text_output + offset;
|
||||
out = (typeof(out))(unsigned long)efi_early->text_output;
|
||||
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)
|
||||
{
|
||||
u8 first, len;
|
||||
|
@ -360,7 +367,7 @@ free_struct:
|
|||
return status;
|
||||
}
|
||||
|
||||
static efi_status_t
|
||||
static void
|
||||
setup_efi_pci32(struct boot_params *params, void **pci_handle,
|
||||
unsigned long size)
|
||||
{
|
||||
|
@ -403,8 +410,6 @@ setup_efi_pci32(struct boot_params *params, void **pci_handle,
|
|||
data = (struct setup_data *)rom;
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned long size)
|
||||
{
|
||||
|
@ -506,11 +511,18 @@ setup_efi_pci64(struct boot_params *params, void **pci_handle,
|
|||
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;
|
||||
void **pci_handle = NULL;
|
||||
|
@ -527,7 +539,7 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
|
|||
size, (void **)&pci_handle);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
return;
|
||||
|
||||
status = efi_call_early(locate_handle,
|
||||
EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||
|
@ -538,13 +550,12 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
|
|||
goto free_handle;
|
||||
|
||||
if (efi_early->is64)
|
||||
status = setup_efi_pci64(params, pci_handle, size);
|
||||
setup_efi_pci64(params, pci_handle, size);
|
||||
else
|
||||
status = setup_efi_pci32(params, pci_handle, size);
|
||||
setup_efi_pci32(params, pci_handle, size);
|
||||
|
||||
free_handle:
|
||||
efi_call_early(free_pool, pci_handle);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1380,10 +1391,7 @@ struct boot_params *efi_main(struct efi_config *c,
|
|||
|
||||
setup_graphics(boot_params);
|
||||
|
||||
status = setup_efi_pci(boot_params);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_printk(sys_table, "setup_efi_pci() failed!\n");
|
||||
}
|
||||
setup_efi_pci(boot_params);
|
||||
|
||||
status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
|
||||
sizeof(*gdt), (void **)&gdt);
|
||||
|
|
|
@ -103,4 +103,20 @@ struct efi_uga_draw_protocol {
|
|||
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 */
|
||||
|
|
|
@ -159,30 +159,6 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
|
|||
}
|
||||
#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);
|
||||
|
||||
#else
|
||||
|
|
|
@ -106,14 +106,14 @@ enum 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.
|
||||
*
|
||||
* 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:
|
||||
*/
|
||||
#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)
|
||||
FIX_BTMAP_END =
|
||||
(__end_of_permanent_fixed_addresses ^
|
||||
|
|
|
@ -1284,6 +1284,9 @@ static void remove_siblinginfo(int cpu)
|
|||
|
||||
for_each_cpu(sibling, cpu_sibling_mask(cpu))
|
||||
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_core_mask(cpu));
|
||||
c->phys_proc_id = 0;
|
||||
|
|
|
@ -419,7 +419,6 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
|
|||
adev->driver_data = pdata;
|
||||
pdev = acpi_create_platform_device(adev);
|
||||
if (!IS_ERR_OR_NULL(pdev)) {
|
||||
device_enable_async_suspend(&pdev->dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -254,6 +254,7 @@ struct acpi_create_field_info {
|
|||
u32 field_bit_position;
|
||||
u32 field_bit_length;
|
||||
u16 resource_length;
|
||||
u16 pin_number_index;
|
||||
u8 field_flags;
|
||||
u8 attribute;
|
||||
u8 field_type;
|
||||
|
|
|
@ -264,6 +264,7 @@ struct acpi_object_region_field {
|
|||
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
|
||||
union acpi_operand_object *region_obj; /* Containing op_region object */
|
||||
u8 *resource_buffer; /* resource_template for serial regions/fields */
|
||||
u16 pin_number_index; /* Index relative to previous Connection/Template */
|
||||
};
|
||||
|
||||
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->connection_node = NULL;
|
||||
info->pin_number_index = 0;
|
||||
|
||||
/*
|
||||
* 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->pin_number_index++; /* Index relative to previous Connection() */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
|||
union acpi_operand_object *region_obj2;
|
||||
void *region_context = NULL;
|
||||
struct acpi_connection_info *context;
|
||||
acpi_physical_address address;
|
||||
|
||||
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 */
|
||||
|
||||
handler = handler_desc->address_space.handler;
|
||||
|
||||
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)));
|
||||
address = (region_obj->region.address + region_offset);
|
||||
|
||||
/*
|
||||
* Special handling for generic_serial_bus and general_purpose_io:
|
||||
* There are three extra parameters that must be passed to the
|
||||
* handler via the context:
|
||||
* 1) Connection buffer, a resource template from Connection() op.
|
||||
* 2) Length of the above buffer.
|
||||
* 3) Actual access length from the access_as() op.
|
||||
* 1) Connection buffer, a resource template from Connection() op
|
||||
* 2) Length of the above buffer
|
||||
* 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) ||
|
||||
(region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) &&
|
||||
if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
|
||||
context && field_obj) {
|
||||
|
||||
/* 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->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 &
|
||||
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
|
||||
|
@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
|
|||
|
||||
/* Call the handler */
|
||||
|
||||
status = handler(function,
|
||||
(region_obj->region.address + region_offset),
|
||||
bit_width, value, context,
|
||||
status = handler(function, address, bit_width, value, context,
|
||||
region_obj2->extra.region_context);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
|
||||
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;
|
||||
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 */
|
||||
|
|
|
@ -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.pin_number_index = info->pin_number_index;
|
||||
|
||||
/* Allow full data read from EC address space */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.ids = container_device_ids,
|
||||
.attach = container_device_attach,
|
||||
|
@ -106,6 +113,7 @@ static struct acpi_scan_handler container_handler = {
|
|||
.hotplug = {
|
||||
.enabled = 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) {
|
||||
count = snprintf(&modalias[len], size, "%s:", id->id);
|
||||
if (count < 0)
|
||||
return EINVAL;
|
||||
return -EINVAL;
|
||||
if (count >= size)
|
||||
return -ENOMEM;
|
||||
len += count;
|
||||
|
@ -2189,6 +2189,9 @@ static void acpi_bus_attach(struct acpi_device *device)
|
|||
ok:
|
||||
list_for_each_entry(child, &device->children, node)
|
||||
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"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.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 */
|
||||
{
|
||||
|
|
|
@ -188,31 +188,31 @@ static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
|
|||
};
|
||||
|
||||
static struct l3_masters_data omap_l3_masters[] = {
|
||||
{ 0x0 , "MPU"},
|
||||
{ 0x10, "CS_ADP"},
|
||||
{ 0x14, "xxx"},
|
||||
{ 0x20, "DSP"},
|
||||
{ 0x30, "IVAHD"},
|
||||
{ 0x40, "ISS"},
|
||||
{ 0x44, "DucatiM3"},
|
||||
{ 0x48, "FaceDetect"},
|
||||
{ 0x50, "SDMA_Rd"},
|
||||
{ 0x54, "SDMA_Wr"},
|
||||
{ 0x58, "xxx"},
|
||||
{ 0x5C, "xxx"},
|
||||
{ 0x60, "SGX"},
|
||||
{ 0x70, "DSS"},
|
||||
{ 0x80, "C2C"},
|
||||
{ 0x88, "xxx"},
|
||||
{ 0x8C, "xxx"},
|
||||
{ 0x90, "HSI"},
|
||||
{ 0xA0, "MMC1"},
|
||||
{ 0xA4, "MMC2"},
|
||||
{ 0xA8, "MMC6"},
|
||||
{ 0xB0, "UNIPRO1"},
|
||||
{ 0xC0, "USBHOSTHS"},
|
||||
{ 0xC4, "USBOTGHS"},
|
||||
{ 0xC8, "USBHOSTFS"}
|
||||
{ 0x00, "MPU"},
|
||||
{ 0x04, "CS_ADP"},
|
||||
{ 0x05, "xxx"},
|
||||
{ 0x08, "DSP"},
|
||||
{ 0x0C, "IVAHD"},
|
||||
{ 0x10, "ISS"},
|
||||
{ 0x11, "DucatiM3"},
|
||||
{ 0x12, "FaceDetect"},
|
||||
{ 0x14, "SDMA_Rd"},
|
||||
{ 0x15, "SDMA_Wr"},
|
||||
{ 0x16, "xxx"},
|
||||
{ 0x17, "xxx"},
|
||||
{ 0x18, "SGX"},
|
||||
{ 0x1C, "DSS"},
|
||||
{ 0x20, "C2C"},
|
||||
{ 0x22, "xxx"},
|
||||
{ 0x23, "xxx"},
|
||||
{ 0x24, "HSI"},
|
||||
{ 0x28, "MMC1"},
|
||||
{ 0x29, "MMC2"},
|
||||
{ 0x2A, "MMC6"},
|
||||
{ 0x2C, "UNIPRO1"},
|
||||
{ 0x30, "USBHOSTHS"},
|
||||
{ 0x31, "USBOTGHS"},
|
||||
{ 0x32, "USBHOSTFS"}
|
||||
};
|
||||
|
||||
static struct l3_flagmux_data *omap_l3_flagmux[] = {
|
||||
|
|
|
@ -1289,6 +1289,8 @@ err_get_freq:
|
|||
per_cpu(cpufreq_cpu_data, j) = NULL;
|
||||
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||
|
||||
up_write(&policy->rwsem);
|
||||
|
||||
if (cpufreq_driver->exit)
|
||||
cpufreq_driver->exit(policy);
|
||||
err_set_policy_cpu:
|
||||
|
@ -1656,6 +1658,8 @@ void cpufreq_suspend(void)
|
|||
if (!cpufreq_driver)
|
||||
return;
|
||||
|
||||
cpufreq_suspended = true;
|
||||
|
||||
if (!has_target())
|
||||
return;
|
||||
|
||||
|
@ -1670,8 +1674,6 @@ void cpufreq_suspend(void)
|
|||
pr_err("%s: Failed to suspend driver: %p\n", __func__,
|
||||
policy);
|
||||
}
|
||||
|
||||
cpufreq_suspended = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1687,13 +1689,13 @@ void cpufreq_resume(void)
|
|||
if (!cpufreq_driver)
|
||||
return;
|
||||
|
||||
cpufreq_suspended = false;
|
||||
|
||||
if (!has_target())
|
||||
return;
|
||||
|
||||
pr_debug("%s: Resuming Governors\n", __func__);
|
||||
|
||||
cpufreq_suspended = false;
|
||||
|
||||
list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
|
||||
if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
|
||||
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;
|
||||
|
||||
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);
|
||||
c->paused = false;
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
|
|||
obj-$(CONFIG_UEFI_CPER) += cper.o
|
||||
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.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 acpi_resource_gpio *agpio;
|
||||
struct acpi_resource *ares;
|
||||
int pin_index = (int)address;
|
||||
acpi_status status;
|
||||
bool pull_up;
|
||||
int length;
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
struct acpi_gpio_connection *conn;
|
||||
struct gpio_desc *desc;
|
||||
|
|
|
@ -413,12 +413,12 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|||
return;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(parent_irq, parent_handler);
|
||||
/*
|
||||
* The parent irqchip is already using the chip_data for this
|
||||
* irqchip, so our callbacks simply use the handler_data.
|
||||
*/
|
||||
irq_set_handler_data(parent_irq, gpiochip);
|
||||
irq_set_chained_handler(parent_irq, parent_handler);
|
||||
}
|
||||
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);
|
||||
|
||||
/* No particular flag request, return here... */
|
||||
if (flags & GPIOD_FLAGS_BIT_DIR_SET)
|
||||
if (!(flags & GPIOD_FLAGS_BIT_DIR_SET))
|
||||
return desc;
|
||||
|
||||
/* 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_regs_sorted(ring));
|
||||
|
||||
ret = init_hash_table(ring, cmd_tables, cmd_table_count);
|
||||
if (ret) {
|
||||
DRM_ERROR("CMD: cmd_parser_init failed!\n");
|
||||
fini_hash_table(ring);
|
||||
return ret;
|
||||
if (hash_empty(ring->cmd_hash)) {
|
||||
ret = init_hash_table(ring, cmd_tables, cmd_table_count);
|
||||
if (ret) {
|
||||
DRM_ERROR("CMD: cmd_parser_init failed!\n");
|
||||
fini_hash_table(ring);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
pipe_config->has_hdmi_sink = true;
|
||||
|
||||
if (tmp & HDMI_MODE_SELECT_HDMI)
|
||||
if (tmp & SDVO_AUDIO_ENABLE)
|
||||
pipe_config->has_audio = true;
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev) &&
|
||||
|
|
|
@ -4803,7 +4803,7 @@ struct bonaire_mqd
|
|||
*/
|
||||
static int cik_cp_compute_resume(struct radeon_device *rdev)
|
||||
{
|
||||
int r, i, idx;
|
||||
int r, i, j, idx;
|
||||
u32 tmp;
|
||||
bool use_doorbell = true;
|
||||
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;
|
||||
if (RREG32(CP_HQD_ACTIVE) & 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))
|
||||
break;
|
||||
udelay(1);
|
||||
|
@ -7751,17 +7751,17 @@ static inline u32 cik_get_ih_wptr(struct radeon_device *rdev)
|
|||
wptr = RREG32(IH_RB_WPTR);
|
||||
|
||||
if (wptr & RB_OVERFLOW) {
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
||||
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);
|
||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||
tmp = RREG32(IH_RB_CNTL);
|
||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||
WREG32(IH_RB_CNTL, tmp);
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
}
|
||||
return (wptr & rdev->ih.ptr_mask);
|
||||
}
|
||||
|
@ -8251,6 +8251,7 @@ restart_ih:
|
|||
/* wptr/rptr are in bytes! */
|
||||
rptr += 16;
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
WREG32(IH_RB_RPTR, rptr);
|
||||
}
|
||||
if (queue_hotplug)
|
||||
schedule_work(&rdev->hotplug_work);
|
||||
|
@ -8259,7 +8260,6 @@ restart_ih:
|
|||
if (queue_thermal)
|
||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||
rdev->ih.rptr = rptr;
|
||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
||||
atomic_set(&rdev->ih.lock, 0);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (wptr & RB_OVERFLOW) {
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
||||
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);
|
||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||
tmp = RREG32(IH_RB_CNTL);
|
||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||
WREG32(IH_RB_CNTL, tmp);
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
}
|
||||
return (wptr & rdev->ih.ptr_mask);
|
||||
}
|
||||
|
@ -5137,6 +5137,7 @@ restart_ih:
|
|||
/* wptr/rptr are in bytes! */
|
||||
rptr += 16;
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
WREG32(IH_RB_RPTR, rptr);
|
||||
}
|
||||
if (queue_hotplug)
|
||||
schedule_work(&rdev->hotplug_work);
|
||||
|
@ -5145,7 +5146,6 @@ restart_ih:
|
|||
if (queue_thermal && rdev->pm.dpm_enabled)
|
||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||
rdev->ih.rptr = rptr;
|
||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
||||
atomic_set(&rdev->ih.lock, 0);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (wptr & RB_OVERFLOW) {
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
||||
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);
|
||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||
tmp = RREG32(IH_RB_CNTL);
|
||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||
WREG32(IH_RB_CNTL, tmp);
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
}
|
||||
return (wptr & rdev->ih.ptr_mask);
|
||||
}
|
||||
|
@ -4048,6 +4048,7 @@ restart_ih:
|
|||
/* wptr/rptr are in bytes! */
|
||||
rptr += 16;
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
WREG32(IH_RB_RPTR, rptr);
|
||||
}
|
||||
if (queue_hotplug)
|
||||
schedule_work(&rdev->hotplug_work);
|
||||
|
@ -4056,7 +4057,6 @@ restart_ih:
|
|||
if (queue_thermal && rdev->pm.dpm_enabled)
|
||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||
rdev->ih.rptr = rptr;
|
||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
||||
atomic_set(&rdev->ih.lock, 0);
|
||||
|
||||
/* 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_use_pflipirq;
|
||||
extern int radeon_bapm;
|
||||
extern int radeon_backlight;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
{ 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 */
|
||||
{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
|
|
|
@ -181,6 +181,7 @@ int radeon_vm_block_size = -1;
|
|||
int radeon_deep_color = 0;
|
||||
int radeon_use_pflipirq = 2;
|
||||
int radeon_bapm = -1;
|
||||
int radeon_backlight = -1;
|
||||
|
||||
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
|
||||
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_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[] = {
|
||||
radeon_PCI_IDS
|
||||
};
|
||||
|
|
|
@ -158,10 +158,43 @@ radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8
|
|||
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
|
||||
radeon_link_encoder_connector(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct drm_encoder *encoder;
|
||||
|
@ -174,13 +207,8 @@ radeon_link_encoder_connector(struct drm_device *dev)
|
|||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
if (radeon_encoder->devices & radeon_connector->devices) {
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
||||
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;
|
||||
}
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
|
||||
radeon_encoder_add_backlight(radeon_encoder, connector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6316,17 +6316,17 @@ static inline u32 si_get_ih_wptr(struct radeon_device *rdev)
|
|||
wptr = RREG32(IH_RB_WPTR);
|
||||
|
||||
if (wptr & RB_OVERFLOW) {
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 16). Hopefully
|
||||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
|
||||
wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
|
||||
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);
|
||||
rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
|
||||
tmp = RREG32(IH_RB_CNTL);
|
||||
tmp |= IH_WPTR_OVERFLOW_CLEAR;
|
||||
WREG32(IH_RB_CNTL, tmp);
|
||||
wptr &= ~RB_OVERFLOW;
|
||||
}
|
||||
return (wptr & rdev->ih.ptr_mask);
|
||||
}
|
||||
|
@ -6664,13 +6664,13 @@ restart_ih:
|
|||
/* wptr/rptr are in bytes! */
|
||||
rptr += 16;
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
WREG32(IH_RB_RPTR, rptr);
|
||||
}
|
||||
if (queue_hotplug)
|
||||
schedule_work(&rdev->hotplug_work);
|
||||
if (queue_thermal && rdev->pm.dpm_enabled)
|
||||
schedule_work(&rdev->pm.dpm.thermal.work);
|
||||
rdev->ih.rptr = rptr;
|
||||
WREG32(IH_RB_RPTR, rdev->ih.rptr);
|
||||
atomic_set(&rdev->ih.lock, 0);
|
||||
|
||||
/* make sure wptr hasn't changed while processing */
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
# 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) += i2ccore.o
|
||||
obj-$(CONFIG_I2C) += i2c-core.o
|
||||
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
|
||||
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.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->control |= ISMT_DESC_BLK;
|
||||
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 {
|
||||
/* Block Read */
|
||||
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->control |= ISMT_DESC_I2C;
|
||||
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 {
|
||||
/* i2c Block Read */
|
||||
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);
|
||||
if (ret) {
|
||||
dev_err(i2c->dev,
|
||||
"PIO: Failed to send SELECT command!\n");
|
||||
"PIO: Failed to send READ command!\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@
|
|||
#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
|
||||
#define RCAR_IRQ_STOP (MST)
|
||||
|
||||
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE))
|
||||
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR))
|
||||
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0xFF)
|
||||
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF)
|
||||
|
||||
#define ID_LAST_MSG (1 << 0)
|
||||
#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 int div;
|
||||
|
||||
/* SCL rate = (clk rate) / (8 * DIV) */
|
||||
div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);
|
||||
|
||||
/* The lower and upper half of the CLKDIV reg describe the length of
|
||||
* SCL low & high periods. */
|
||||
div = DIV_ROUND_UP(div, 2);
|
||||
/* set DIV = DIVH = DIVL
|
||||
* SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
|
||||
* = (clk rate) / (16 * (DIV + 1))
|
||||
*/
|
||||
div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;
|
||||
|
||||
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;
|
||||
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) {
|
||||
dev_err(i2c_dev->dev,
|
||||
"Enabling fast clk failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = clk_prepare_enable(i2c_dev->div_clk);
|
||||
ret = clk_enable(i2c_dev->div_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(i2c_dev->dev,
|
||||
"Enabling div clk failed, err %d\n", ret);
|
||||
clk_disable_unprepare(i2c_dev->fast_clk);
|
||||
clk_disable(i2c_dev->fast_clk);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
clk_disable_unprepare(i2c_dev->fast_clk);
|
||||
clk_disable(i2c_dev->fast_clk);
|
||||
}
|
||||
|
||||
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
||||
{
|
||||
u32 val;
|
||||
int err = 0;
|
||||
int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
|
||||
u32 clk_divisor;
|
||||
|
||||
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, 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 */
|
||||
clk_divisor = i2c_dev->hw->clk_divisor_hs_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;
|
||||
int irq;
|
||||
int ret = 0;
|
||||
int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
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);
|
||||
|
||||
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);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to initialize i2c controller");
|
||||
return ret;
|
||||
goto unprepare_div_clk;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
|
||||
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
|
||||
if (ret) {
|
||||
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);
|
||||
|
@ -803,16 +822,30 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
|||
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
|
||||
return ret;
|
||||
goto unprepare_div_clk;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
(based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
|
||||
(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>
|
||||
|
@ -78,6 +80,368 @@ void i2c_transfer_trace_unreg(void)
|
|||
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,
|
||||
|
|
|
@ -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"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Asus X450LCP */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Avatar AVIU-145A6 */
|
||||
.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);
|
||||
|
||||
if ((len > (bp->dev->mtu + ETH_HLEN)) &&
|
||||
(ntohs(skb->protocol) != 0x8100)) {
|
||||
if (len > (bp->dev->mtu + ETH_HLEN) &&
|
||||
skb->protocol != htons(0x8100) &&
|
||||
skb->protocol != htons(ETH_P_8021AD)) {
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
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);
|
||||
|
||||
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);
|
||||
goto drop_it_no_recycle;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include "macb.h"
|
||||
|
||||
|
@ -2071,7 +2070,6 @@ static int __init macb_probe(struct platform_device *pdev)
|
|||
struct phy_device *phydev;
|
||||
u32 config;
|
||||
int err = -ENXIO;
|
||||
struct pinctrl *pinctrl;
|
||||
const char *mac;
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
@ -2080,15 +2078,6 @@ static int __init macb_probe(struct platform_device *pdev)
|
|||
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;
|
||||
dev = alloc_etherdev(sizeof(*bp));
|
||||
if (!dev)
|
||||
|
|
|
@ -78,13 +78,13 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
|
|||
#endif /* CONFIG_PCI_MSI */
|
||||
|
||||
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_PARM_DESC(num_vfs, "enable #num_vfs functions if num_vfs > 0\n"
|
||||
"num_vfs=port1,port2,port1+2");
|
||||
|
||||
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_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)\n"
|
||||
"probe_vf=port1,port2,port1+2");
|
||||
|
|
|
@ -135,6 +135,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
|
|||
int i, j;
|
||||
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
|
||||
|
||||
spin_lock(&adapter->tx_clean_lock);
|
||||
cmd_buf = tx_ring->cmd_buf_arr;
|
||||
for (i = 0; i < tx_ring->num_desc; i++) {
|
||||
buffrag = cmd_buf->frag_array;
|
||||
|
@ -158,6 +159,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
|
|||
}
|
||||
cmd_buf++;
|
||||
}
|
||||
spin_unlock(&adapter->tx_clean_lock);
|
||||
}
|
||||
|
||||
void netxen_free_sw_resources(struct netxen_adapter *adapter)
|
||||
|
@ -1792,9 +1794,9 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
|
|||
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();
|
||||
|
||||
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;
|
||||
|
||||
smp_mb();
|
||||
spin_lock(&adapter->tx_clean_lock);
|
||||
netif_carrier_off(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_release_tx_buffers(adapter);
|
||||
spin_unlock(&adapter->tx_clean_lock);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (qlcnic_83xx_lockless_flash_read32(adapter,
|
||||
QLC_83XX_IDC_FLASH_PARAM_ADDR,
|
||||
(u8 *)&idc_params, 1)) {
|
||||
if (qlcnic_83xx_flash_read32(adapter, QLC_83XX_IDC_FLASH_PARAM_ADDR,
|
||||
(u8 *)&idc_params, 1)) {
|
||||
dev_info(&adapter->pdev->dev,
|
||||
"%s:failed to get IDC params from flash\n", __func__);
|
||||
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_esw_statistics port_stats;
|
||||
struct qlcnic_mac_statistics mac_stats;
|
||||
int index, ret, length, size, tx_size, ring;
|
||||
int index, ret, length, size, ring;
|
||||
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++) {
|
||||
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
|
||||
if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
|
||||
tx_ring = &adapter->tx_ring[ring];
|
||||
data = qlcnic_fill_tx_queue_stats(data, tx_ring);
|
||||
qlcnic_update_stats(adapter);
|
||||
} else {
|
||||
data += QLCNIC_TX_STATS_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
memset(data, 0, stats->n_stats * sizeof(u64));
|
||||
length = QLCNIC_STATS_LEN;
|
||||
for (index = 0; index < length; index++) {
|
||||
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)) {
|
||||
dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(priv->stmmac_clk);
|
||||
goto error_clk_get;
|
||||
/* If failed to obtain stmmac_clk and specific clk_csr value
|
||||
* 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);
|
||||
|
||||
|
|
|
@ -387,6 +387,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
|||
int hdr_offset;
|
||||
u32 net_trans_info;
|
||||
u32 hash;
|
||||
u32 skb_length = skb->len;
|
||||
|
||||
|
||||
/* We will atmost need two pages to describe the rndis
|
||||
|
@ -562,7 +563,7 @@ do_send:
|
|||
|
||||
drop:
|
||||
if (ret == 0) {
|
||||
net->stats.tx_bytes += skb->len;
|
||||
net->stats.tx_bytes += skb_length;
|
||||
net->stats.tx_packets++;
|
||||
} else {
|
||||
kfree(packet);
|
||||
|
|
|
@ -112,17 +112,15 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Requires RTNL */
|
||||
static int macvtap_set_queue(struct net_device *dev, struct file *file,
|
||||
struct macvtap_queue *q)
|
||||
{
|
||||
struct macvlan_dev *vlan = netdev_priv(dev);
|
||||
int err = -EBUSY;
|
||||
|
||||
rtnl_lock();
|
||||
if (vlan->numqueues == MAX_MACVTAP_QUEUES)
|
||||
goto out;
|
||||
return -EBUSY;
|
||||
|
||||
err = 0;
|
||||
rcu_assign_pointer(q->vlan, vlan);
|
||||
rcu_assign_pointer(vlan->taps[vlan->numvtaps], q);
|
||||
sock_hold(&q->sk);
|
||||
|
@ -136,9 +134,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file,
|
|||
vlan->numvtaps++;
|
||||
vlan->numqueues++;
|
||||
|
||||
out:
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
int err;
|
||||
int err = -ENODEV;
|
||||
|
||||
err = -ENODEV;
|
||||
rtnl_lock();
|
||||
dev = dev_get_by_macvtap_minor(iminor(inode));
|
||||
if (!dev)
|
||||
goto out;
|
||||
|
||||
|
@ -498,6 +495,7 @@ out:
|
|||
if (dev)
|
||||
dev_put(dev);
|
||||
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <linux/mdio.h>
|
||||
|
||||
/* 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_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
|
||||
#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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
u32 ocp_data;
|
||||
int i, ret;
|
||||
|
||||
r8152b_reset_packet_filter(tp);
|
||||
|
||||
|
@ -1992,14 +2016,7 @@ static int rtl_enable(struct r8152 *tp)
|
|||
|
||||
rxdy_gated_en(tp, false);
|
||||
|
||||
INIT_LIST_HEAD(&tp->rx_done);
|
||||
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;
|
||||
return rtl_start_rx(tp);
|
||||
}
|
||||
|
||||
static int rtl8152_enable(struct r8152 *tp)
|
||||
|
@ -2083,8 +2100,7 @@ static void rtl_disable(struct r8152 *tp)
|
|||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
for (i = 0; i < RTL8152_MAX_RX; i++)
|
||||
usb_kill_urb(tp->rx_info[i].urb);
|
||||
rtl_stop_rx(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)
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
@ -2307,8 +2301,6 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp)
|
|||
r8152_mdio_write(tp, MII_BMCR, data);
|
||||
}
|
||||
|
||||
rtl_clear_bp(tp);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
r8153_clear_bp(tp);
|
||||
|
||||
if (tp->version == RTL_VER_03) {
|
||||
data = ocp_reg_read(tp, OCP_EEE_CFG);
|
||||
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);
|
||||
usb_kill_urb(tp->intr_urb);
|
||||
cancel_delayed_work_sync(&tp->schedule);
|
||||
tasklet_disable(&tp->tl);
|
||||
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
|
||||
rtl_stop_rx(tp);
|
||||
rtl_runtime_suspend_enable(tp, true);
|
||||
} else {
|
||||
tasklet_disable(&tp->tl);
|
||||
tp->rtl_ops.down(tp);
|
||||
tasklet_enable(&tp->tl);
|
||||
}
|
||||
tasklet_enable(&tp->tl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -3206,18 +3197,19 @@ static int rtl8152_resume(struct usb_interface *intf)
|
|||
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
|
||||
rtl_runtime_suspend_enable(tp, false);
|
||||
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
set_bit(WORK_ENABLE, &tp->flags);
|
||||
if (tp->speed & LINK_STATUS)
|
||||
tp->rtl_ops.disable(tp);
|
||||
rtl_start_rx(tp);
|
||||
} else {
|
||||
tp->rtl_ops.up(tp);
|
||||
rtl8152_set_speed(tp, AUTONEG_ENABLE,
|
||||
tp->mii.supports_gmii ?
|
||||
SPEED_1000 : SPEED_100,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -3623,7 +3615,7 @@ static void rtl8153_unload(struct r8152 *tp)
|
|||
if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
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)
|
||||
|
@ -3788,7 +3780,11 @@ static void rtl8152_disconnect(struct usb_interface *intf)
|
|||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
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);
|
||||
unregister_netdev(tp->netdev);
|
||||
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 */
|
||||
bool secure = strncmp(pp->name, "security-", 9) == 0;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||
return 0;
|
||||
|
||||
if (!of_kset || !of_node_is_attached(np))
|
||||
return 0;
|
||||
|
||||
|
@ -158,6 +161,9 @@ int __of_attach_node_sysfs(struct device_node *np)
|
|||
struct property *pp;
|
||||
int rc;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||
return 0;
|
||||
|
||||
if (!of_kset)
|
||||
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)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||
return;
|
||||
|
||||
/* at early boot, bail here and defer setup to of_init() */
|
||||
if (of_kset && of_node_is_attached(np))
|
||||
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,
|
||||
struct property *oldprop)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||
return;
|
||||
|
||||
/* At early boot, bail out and defer setup to of_init() */
|
||||
if (!of_kset)
|
||||
return;
|
||||
|
@ -1847,6 +1859,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
|
|||
{
|
||||
struct property *pp;
|
||||
|
||||
of_aliases = of_find_node_by_path("/aliases");
|
||||
of_chosen = of_find_node_by_path("/chosen");
|
||||
if (of_chosen == NULL)
|
||||
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_aliases = of_find_node_by_path("/aliases");
|
||||
if (!of_aliases)
|
||||
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)
|
||||
return false;
|
||||
return add_preferred_console(name, index, NULL);
|
||||
return !add_preferred_console(name, index, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_console_check);
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@ void __of_detach_node_sysfs(struct device_node *np)
|
|||
{
|
||||
struct property *pp;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SYSFS))
|
||||
return;
|
||||
|
||||
BUG_ON(!of_node_is_initialized(np));
|
||||
if (!of_kset)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (base > MAX_PHYS_ADDR) {
|
||||
|
@ -937,10 +941,10 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
|
|||
return;
|
||||
}
|
||||
|
||||
if (base + size > MAX_PHYS_ADDR) {
|
||||
pr_warning("Ignoring memory range 0x%lx - 0x%llx\n",
|
||||
ULONG_MAX, base + size);
|
||||
size = MAX_PHYS_ADDR - base;
|
||||
if (base + size - 1 > MAX_PHYS_ADDR) {
|
||||
pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
|
||||
((u64)MAX_PHYS_ADDR) + 1, base + size);
|
||||
size = MAX_PHYS_ADDR - base + 1;
|
||||
}
|
||||
|
||||
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_ALIAS("platform:rtc-efi");
|
||||
MODULE_AUTHOR("dann frazier <dannf@hp.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("EFI RTC driver");
|
||||
|
|
|
@ -22,44 +22,63 @@
|
|||
#define GSBI_CTRL_REG 0x0000
|
||||
#define GSBI_PROTOCOL_SHIFT 4
|
||||
|
||||
struct gsbi_info {
|
||||
struct clk *hclk;
|
||||
u32 mode;
|
||||
u32 crci;
|
||||
};
|
||||
|
||||
static int gsbi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
struct clk *hclk;
|
||||
u32 mode, crci = 0;
|
||||
struct gsbi_info *gsbi;
|
||||
|
||||
gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL);
|
||||
|
||||
if (!gsbi)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_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");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
if (IS_ERR(hclk))
|
||||
return PTR_ERR(hclk);
|
||||
clk_prepare_enable(gsbi->hclk);
|
||||
|
||||
clk_prepare_enable(hclk);
|
||||
|
||||
writel_relaxed((mode << GSBI_PROTOCOL_SHIFT) | crci,
|
||||
writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci,
|
||||
base + GSBI_CTRL_REG);
|
||||
|
||||
/* make sure the gsbi control write is not reordered */
|
||||
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[] = {
|
||||
|
@ -76,6 +95,7 @@ static struct platform_driver gsbi_driver = {
|
|||
.of_match_table = gsbi_dt_match,
|
||||
},
|
||||
.probe = gsbi_probe,
|
||||
.remove = gsbi_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(gsbi_driver);
|
||||
|
|
|
@ -50,18 +50,18 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
|
|||
cache->brun_percent < 100);
|
||||
|
||||
if (*args) {
|
||||
pr_err("'bind' command doesn't take an argument");
|
||||
pr_err("'bind' command doesn't take an argument\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cache->rootdirname) {
|
||||
pr_err("No cache directory specified");
|
||||
pr_err("No cache directory specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* don't permit already bound caches to be re-bound */
|
||||
if (test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||
pr_err("Cache already bound");
|
||||
pr_err("Cache already bound\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ error_open_root:
|
|||
kmem_cache_free(cachefiles_object_jar, fsdef);
|
||||
error_root_object:
|
||||
cachefiles_end_secure(cache, saved_cred);
|
||||
pr_err("Failed to register: %d", ret);
|
||||
pr_err("Failed to register: %d\n", 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,
|
||||
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;
|
||||
}
|
||||
|
@ -475,12 +475,12 @@ static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)
|
|||
_enter(",%s", args);
|
||||
|
||||
if (!*args) {
|
||||
pr_err("Empty directory specified");
|
||||
pr_err("Empty directory specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cache->rootdirname) {
|
||||
pr_err("Second cache directory specified");
|
||||
pr_err("Second cache directory specified\n");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
|
@ -503,12 +503,12 @@ static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
|
|||
_enter(",%s", args);
|
||||
|
||||
if (!*args) {
|
||||
pr_err("Empty security context specified");
|
||||
pr_err("Empty security context specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cache->secctx) {
|
||||
pr_err("Second security context specified");
|
||||
pr_err("Second security context specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -531,7 +531,7 @@ static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args)
|
|||
_enter(",%s", args);
|
||||
|
||||
if (!*args) {
|
||||
pr_err("Empty tag specified");
|
||||
pr_err("Empty tag specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -562,12 +562,12 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
|
|||
goto inval;
|
||||
|
||||
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||
pr_err("cull applied to unready cache");
|
||||
pr_err("cull applied to unready cache\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
||||
pr_err("cull applied to dead cache");
|
||||
pr_err("cull applied to dead cache\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -587,11 +587,11 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
|
|||
|
||||
notdir:
|
||||
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;
|
||||
|
||||
inval:
|
||||
pr_err("cull command requires dirfd and filename");
|
||||
pr_err("cull command requires dirfd and filename\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -614,7 +614,7 @@ static int cachefiles_daemon_debug(struct cachefiles_cache *cache, char *args)
|
|||
return 0;
|
||||
|
||||
inval:
|
||||
pr_err("debug command requires mask");
|
||||
pr_err("debug command requires mask\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -634,12 +634,12 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
|
|||
goto inval;
|
||||
|
||||
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||
pr_err("inuse applied to unready cache");
|
||||
pr_err("inuse applied to unready cache\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
||||
pr_err("inuse applied to dead cache");
|
||||
pr_err("inuse applied to dead cache\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -659,11 +659,11 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
|
|||
|
||||
notdir:
|
||||
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;
|
||||
|
||||
inval:
|
||||
pr_err("inuse command requires dirfd and filename");
|
||||
pr_err("inuse command requires dirfd and filename\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -255,7 +255,7 @@ extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
|
|||
|
||||
#define cachefiles_io_error(___cache, FMT, ...) \
|
||||
do { \
|
||||
pr_err("I/O Error: " FMT, ##__VA_ARGS__); \
|
||||
pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__); \
|
||||
fscache_io_error(&(___cache)->cache); \
|
||||
set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
|
||||
} while (0)
|
||||
|
|
|
@ -84,7 +84,7 @@ error_proc:
|
|||
error_object_jar:
|
||||
misc_deregister(&cachefiles_dev);
|
||||
error_dev:
|
||||
pr_err("failed to register: %d", ret);
|
||||
pr_err("failed to register: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -543,7 +543,7 @@ lookup_again:
|
|||
next, next->d_inode, next->d_inode->i_ino);
|
||||
|
||||
} 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);
|
||||
ret = -ENOBUFS;
|
||||
goto error;
|
||||
|
@ -574,7 +574,7 @@ lookup_again:
|
|||
} else if (!S_ISDIR(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);
|
||||
ret = -ENOBUFS;
|
||||
goto error;
|
||||
|
@ -768,7 +768,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
|||
ASSERT(subdir->d_inode);
|
||||
|
||||
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;
|
||||
goto check_error;
|
||||
}
|
||||
|
@ -796,13 +796,13 @@ check_error:
|
|||
mkdir_error:
|
||||
mutex_unlock(&dir->d_inode->i_mutex);
|
||||
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);
|
||||
|
||||
lookup_error:
|
||||
mutex_unlock(&dir->d_inode->i_mutex);
|
||||
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);
|
||||
|
||||
nomem_d_alloc:
|
||||
|
@ -892,7 +892,7 @@ lookup_error:
|
|||
if (ret == -EIO) {
|
||||
cachefiles_io_error(cache, "Lookup failed");
|
||||
} else if (ret != -ENOMEM) {
|
||||
pr_err("Internal error: %d", ret);
|
||||
pr_err("Internal error: %d\n", ret);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
|
@ -951,7 +951,7 @@ error:
|
|||
}
|
||||
|
||||
if (ret != -ENOMEM) {
|
||||
pr_err("Internal error: %d", ret);
|
||||
pr_err("Internal error: %d\n", ret);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
|
|||
}
|
||||
|
||||
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.name, dentry->d_inode->i_ino,
|
||||
-ret);
|
||||
|
@ -64,7 +64,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
|
|||
if (ret == -ERANGE)
|
||||
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.name, dentry->d_inode->i_ino,
|
||||
-ret);
|
||||
|
@ -85,14 +85,14 @@ error:
|
|||
return ret;
|
||||
|
||||
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);
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
|
||||
bad_type:
|
||||
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.name, dentry->d_inode->i_ino,
|
||||
xtype, type);
|
||||
|
@ -293,7 +293,7 @@ error:
|
|||
return ret;
|
||||
|
||||
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);
|
||||
ret = -EIO;
|
||||
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);
|
||||
|
||||
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(dentry)) {
|
||||
|
@ -2406,13 +2407,19 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
|
|||
*/
|
||||
unsigned int i;
|
||||
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++) {
|
||||
swap(((long *) &dentry->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)
|
||||
|
@ -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,
|
||||
struct dentry *target)
|
||||
static void dentry_unlock_for_move(struct dentry *dentry, struct dentry *target)
|
||||
{
|
||||
if (target->d_parent != dentry->d_parent)
|
||||
spin_unlock(&dentry->d_parent->d_lock);
|
||||
if (target->d_parent != target)
|
||||
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
|
||||
* be preserved in the target - because we're dropping the target
|
||||
* anyway. As such, we can just do a simple memcpy() to copy over
|
||||
* the new name before we switch.
|
||||
*
|
||||
* Note that we have to be a lot more careful about getting the hash
|
||||
* switched - we have to switch the hash value properly even if it
|
||||
* then no longer matches the actual (corrupted) string of the target.
|
||||
* The hash value has to match the hash queue that the dentry is on..
|
||||
* 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
|
||||
* to rehash it without giving it a new name/hash key - whether
|
||||
* we swap or overwrite the names here, resulting name won't match
|
||||
* the reality in filesystem; it's only there for d_path() purposes.
|
||||
* 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
|
||||
|
@ -2506,36 +2517,30 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
|
|||
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_names(dentry, target);
|
||||
swap(dentry->d_name.hash, target->d_name.hash);
|
||||
switch_names(dentry, target, exchange);
|
||||
|
||||
/* ... and switch the parents */
|
||||
/* ... and switch them in the tree */
|
||||
if (IS_ROOT(dentry)) {
|
||||
/* splicing a tree */
|
||||
dentry->d_parent = target->d_parent;
|
||||
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 {
|
||||
/* swapping two dentries */
|
||||
swap(dentry->d_parent, target->d_parent);
|
||||
|
||||
/* And add them back to the (new) parent lists */
|
||||
list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
|
||||
list_move(&target->d_u.d_child, &target->d_parent->d_subdirs);
|
||||
list_move(&dentry->d_u.d_child, &dentry->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(&dentry->d_seq);
|
||||
|
||||
dentry_unlock_parents_for_move(dentry, target);
|
||||
if (exchange)
|
||||
fsnotify_d_move(target);
|
||||
spin_unlock(&target->d_lock);
|
||||
fsnotify_d_move(dentry);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
dentry_unlock_for_move(dentry, target);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2633,45 +2638,6 @@ out_err:
|
|||
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
|
||||
* @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);
|
||||
}
|
||||
write_seqlock(&rename_lock);
|
||||
__d_materialise_dentry(dentry, new);
|
||||
__d_move(new, dentry, false);
|
||||
write_sequnlock(&rename_lock);
|
||||
_d_rehash(new);
|
||||
spin_unlock(&new->d_lock);
|
||||
spin_unlock(&inode->i_lock);
|
||||
security_d_instantiate(new, inode);
|
||||
iput(inode);
|
||||
|
@ -2780,7 +2744,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
|
|||
} else if (IS_ROOT(alias)) {
|
||||
/* Is this an anonymous mountpoint that we
|
||||
* could splice into our tree? */
|
||||
__d_materialise_dentry(dentry, alias);
|
||||
__d_move(alias, dentry, false);
|
||||
write_sequnlock(&rename_lock);
|
||||
goto found;
|
||||
} else {
|
||||
|
@ -2807,13 +2771,9 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
|
|||
actual = __d_instantiate_unique(dentry, inode);
|
||||
if (!actual)
|
||||
actual = dentry;
|
||||
else
|
||||
BUG_ON(!d_unhashed(actual));
|
||||
|
||||
spin_lock(&actual->d_lock);
|
||||
d_rehash(actual);
|
||||
found:
|
||||
_d_rehash(actual);
|
||||
spin_unlock(&actual->d_lock);
|
||||
spin_unlock(&inode->i_lock);
|
||||
out_nolock:
|
||||
if (actual == dentry) {
|
||||
|
|
|
@ -158,7 +158,7 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio)
|
|||
{
|
||||
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);
|
||||
|
||||
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;
|
||||
ssize_t ret = iov_iter_get_pages(ii,
|
||||
&req->pages[req->num_pages],
|
||||
*nbytesp - nbytes,
|
||||
req->max_pages - req->num_pages,
|
||||
&start);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -3104,7 +3104,8 @@ static __be32 nfsd4_encode_splice_read(
|
|||
|
||||
buf->page_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: */
|
||||
buf->tail[0].iov_base = xdr->p;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/buffer_head.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/aio.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)
|
||||
{
|
||||
struct inode *inode = page->mapping->host;
|
||||
int ret = __set_page_dirty_nobuffers(page);
|
||||
|
||||
if (page_has_buffers(page)) {
|
||||
struct inode *inode = page->mapping->host;
|
||||
unsigned nr_dirty = 0;
|
||||
struct buffer_head *bh, *head;
|
||||
|
||||
|
@ -245,6 +246,10 @@ static int nilfs_set_page_dirty(struct page *page)
|
|||
|
||||
if (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;
|
||||
}
|
||||
|
|
|
@ -655,12 +655,9 @@ void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm,
|
|||
clear_bit(bit, res->refmap);
|
||||
}
|
||||
|
||||
|
||||
void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
||||
static void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
|
||||
struct dlm_lock_resource *res)
|
||||
{
|
||||
assert_spin_locked(&res->spinlock);
|
||||
|
||||
res->inflight_locks++;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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,
|
||||
struct dlm_lock_resource *res)
|
||||
{
|
||||
|
@ -894,10 +898,8 @@ lookup:
|
|||
/* finally add the lockres to its hash bucket */
|
||||
__dlm_insert_lockres(dlm, res);
|
||||
|
||||
/* Grab inflight ref to pin the resource */
|
||||
spin_lock(&res->spinlock);
|
||||
dlm_lockres_grab_inflight_ref(dlm, res);
|
||||
spin_unlock(&res->spinlock);
|
||||
/* since this lockres is new it doesn't not require the spinlock */
|
||||
__dlm_lockres_grab_inflight_ref(dlm, res);
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -2532,6 +2532,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb)
|
|||
kfree(osb->journal);
|
||||
kfree(osb->local_alloc_copy);
|
||||
kfree(osb->uuid_str);
|
||||
kfree(osb->vol_label);
|
||||
ocfs2_put_dlm_debug(osb->osb_dlm_debug);
|
||||
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) {
|
||||
struct vm_area_struct *vma = find_vma(walk->mm, addr);
|
||||
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) {
|
||||
vm_end = end;
|
||||
} else {
|
||||
vm_end = min(end, vma->vm_end);
|
||||
if (vma->vm_flags & VM_SOFTDIRTY)
|
||||
pme.pme |= PM_STATUS2(pm->v2, __PM_SOFT_DIRTY);
|
||||
if (vma)
|
||||
hole_end = min(end, vma->vm_start);
|
||||
else
|
||||
hole_end = end;
|
||||
|
||||
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);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -298,7 +298,10 @@ cg_found:
|
|||
ufsi->i_oeftflag = 0;
|
||||
ufsi->i_dir_start_lookup = 0;
|
||||
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);
|
||||
|
||||
if (uspi->fs_magic == UFS2_MAGIC) {
|
||||
|
@ -337,6 +340,7 @@ cg_found:
|
|||
fail_remove_inode:
|
||||
unlock_ufs(sb);
|
||||
clear_nlink(inode);
|
||||
unlock_new_inode(inode);
|
||||
iput(inode);
|
||||
UFSD("EXIT (FAILED): err %d\n", 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);
|
||||
if (!err) {
|
||||
unlock_new_inode(inode);
|
||||
d_instantiate(dentry, inode);
|
||||
return 0;
|
||||
}
|
||||
inode_dec_link_count(inode);
|
||||
unlock_new_inode(inode);
|
||||
iput(inode);
|
||||
return err;
|
||||
}
|
||||
|
@ -155,6 +157,7 @@ out_notlocked:
|
|||
|
||||
out_fail:
|
||||
inode_dec_link_count(inode);
|
||||
unlock_new_inode(inode);
|
||||
iput(inode);
|
||||
goto out;
|
||||
}
|
||||
|
@ -210,6 +213,7 @@ out:
|
|||
out_fail:
|
||||
inode_dec_link_count(inode);
|
||||
inode_dec_link_count(inode);
|
||||
unlock_new_inode(inode);
|
||||
iput (inode);
|
||||
inode_dec_link_count(dir);
|
||||
unlock_ufs(dir->i_sb);
|
||||
|
|
|
@ -118,6 +118,7 @@ struct acpi_device;
|
|||
struct acpi_hotplug_profile {
|
||||
struct kobject kobj;
|
||||
int (*scan_dependent)(struct acpi_device *adev);
|
||||
void (*notify_online)(struct acpi_device *adev);
|
||||
bool enabled: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)
|
||||
{
|
||||
return current->flags & PF_SPREAD_PAGE;
|
||||
return task_spread_page(current);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче