Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
commit
580bdf5650
|
@ -1,12 +0,0 @@
|
||||||
What: /sys/devices/.../deferred_probe
|
|
||||||
Date: August 2016
|
|
||||||
Contact: Ben Hutchings <ben.hutchings@codethink.co.uk>
|
|
||||||
Description:
|
|
||||||
The /sys/devices/.../deferred_probe attribute is
|
|
||||||
present for all devices. If a driver detects during
|
|
||||||
probing a device that a related device is not yet
|
|
||||||
ready, it may defer probing of the first device. The
|
|
||||||
kernel will retry probing the first device after any
|
|
||||||
other device is successfully probed. This attribute
|
|
||||||
reads as 1 if probing of this device is currently
|
|
||||||
deferred, or 0 otherwise.
|
|
|
@ -62,6 +62,9 @@ wants to support one of the below features, it should adapt the bindings below.
|
||||||
"irq" and "wakeup" names are recognized by I2C core, other names are
|
"irq" and "wakeup" names are recognized by I2C core, other names are
|
||||||
left to individual drivers.
|
left to individual drivers.
|
||||||
|
|
||||||
|
- host-notify
|
||||||
|
device uses SMBus host notify protocol instead of interrupt line.
|
||||||
|
|
||||||
- multi-master
|
- multi-master
|
||||||
states that there is another master active on this bus. The OS can use
|
states that there is another master active on this bus. The OS can use
|
||||||
this information to adapt power management to keep the arbitration awake
|
this information to adapt power management to keep the arbitration awake
|
||||||
|
@ -81,6 +84,11 @@ Binding may contain optional "interrupts" property, describing interrupts
|
||||||
used by the device. I2C core will assign "irq" interrupt (or the very first
|
used by the device. I2C core will assign "irq" interrupt (or the very first
|
||||||
interrupt if not using interrupt names) as primary interrupt for the slave.
|
interrupt if not using interrupt names) as primary interrupt for the slave.
|
||||||
|
|
||||||
|
Alternatively, devices supporting SMbus Host Notify, and connected to
|
||||||
|
adapters that support this feature, may use "host-notify" property. I2C
|
||||||
|
core will create a virtual interrupt for Host Notify and assign it as
|
||||||
|
primary interrupt for the slave.
|
||||||
|
|
||||||
Also, if device is marked as a wakeup source, I2C core will set up "wakeup"
|
Also, if device is marked as a wakeup source, I2C core will set up "wakeup"
|
||||||
interrupt for the device. If "wakeup" interrupt name is not present in the
|
interrupt for the device. If "wakeup" interrupt name is not present in the
|
||||||
binding, then primary interrupt will be used as wakeup interrupt.
|
binding, then primary interrupt will be used as wakeup interrupt.
|
||||||
|
|
|
@ -5,7 +5,7 @@ Required properties:
|
||||||
- compatible: "sigma,smp8758-nand"
|
- compatible: "sigma,smp8758-nand"
|
||||||
- reg: address/size of nfc_reg, nfc_mem, and pbus_reg
|
- reg: address/size of nfc_reg, nfc_mem, and pbus_reg
|
||||||
- dmas: reference to the DMA channel used by the controller
|
- dmas: reference to the DMA channel used by the controller
|
||||||
- dma-names: "nfc_sbox"
|
- dma-names: "rxtx"
|
||||||
- clocks: reference to the system clock
|
- clocks: reference to the system clock
|
||||||
- #address-cells: <1>
|
- #address-cells: <1>
|
||||||
- #size-cells: <0>
|
- #size-cells: <0>
|
||||||
|
@ -17,9 +17,9 @@ Example:
|
||||||
|
|
||||||
nandc: nand-controller@2c000 {
|
nandc: nand-controller@2c000 {
|
||||||
compatible = "sigma,smp8758-nand";
|
compatible = "sigma,smp8758-nand";
|
||||||
reg = <0x2c000 0x30 0x2d000 0x800 0x20000 0x1000>;
|
reg = <0x2c000 0x30>, <0x2d000 0x800>, <0x20000 0x1000>;
|
||||||
dmas = <&dma0 3>;
|
dmas = <&dma0 3>;
|
||||||
dma-names = "nfc_sbox";
|
dma-names = "rxtx";
|
||||||
clocks = <&clkgen SYS_CLK>;
|
clocks = <&clkgen SYS_CLK>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
Required properties:
|
Required properties:
|
||||||
- reg - The ID number for the phy, usually a small integer
|
- reg - The ID number for the phy, usually a small integer
|
||||||
- ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
|
- ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
|
||||||
for applicable values
|
for applicable values. Required only if interface type is
|
||||||
|
PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_RXID
|
||||||
- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
|
- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
|
||||||
for applicable values
|
for applicable values. Required only if interface type is
|
||||||
|
PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID
|
||||||
- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
|
- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
|
||||||
for applicable values
|
for applicable values
|
||||||
|
|
||||||
|
|
17
MAINTAINERS
17
MAINTAINERS
|
@ -2193,14 +2193,6 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||||
S: Supported
|
S: Supported
|
||||||
F: sound/soc/atmel
|
F: sound/soc/atmel
|
||||||
|
|
||||||
ATMEL DMA DRIVER
|
|
||||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|
||||||
S: Supported
|
|
||||||
F: drivers/dma/at_hdmac.c
|
|
||||||
F: drivers/dma/at_hdmac_regs.h
|
|
||||||
F: include/linux/platform_data/dma-atmel.h
|
|
||||||
|
|
||||||
ATMEL XDMA DRIVER
|
ATMEL XDMA DRIVER
|
||||||
M: Ludovic Desroches <ludovic.desroches@atmel.com>
|
M: Ludovic Desroches <ludovic.desroches@atmel.com>
|
||||||
L: linux-arm-kernel@lists.infradead.org
|
L: linux-arm-kernel@lists.infradead.org
|
||||||
|
@ -8184,6 +8176,15 @@ S: Maintained
|
||||||
F: drivers/tty/serial/atmel_serial.c
|
F: drivers/tty/serial/atmel_serial.c
|
||||||
F: include/linux/atmel_serial.h
|
F: include/linux/atmel_serial.h
|
||||||
|
|
||||||
|
MICROCHIP / ATMEL DMA DRIVER
|
||||||
|
M: Ludovic Desroches <ludovic.desroches@microchip.com>
|
||||||
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
L: dmaengine@vger.kernel.org
|
||||||
|
S: Supported
|
||||||
|
F: drivers/dma/at_hdmac.c
|
||||||
|
F: drivers/dma/at_hdmac_regs.h
|
||||||
|
F: include/linux/platform_data/dma-atmel.h
|
||||||
|
|
||||||
MICROCHIP / ATMEL ISC DRIVER
|
MICROCHIP / ATMEL ISC DRIVER
|
||||||
M: Songjun Wu <songjun.wu@microchip.com>
|
M: Songjun Wu <songjun.wu@microchip.com>
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 10
|
PATCHLEVEL = 10
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc3
|
EXTRAVERSION = -rc4
|
||||||
NAME = Roaring Lionus
|
NAME = Roaring Lionus
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
@ -164,22 +164,25 @@ lr .req x30 // link register
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
|
* Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
|
||||||
* <symbol> is within the range +/- 4 GB of the PC.
|
* <symbol> is within the range +/- 4 GB of the PC when running
|
||||||
|
* in core kernel context. In module context, a movz/movk sequence
|
||||||
|
* is used, since modules may be loaded far away from the kernel
|
||||||
|
* when KASLR is in effect.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* @dst: destination register (64 bit wide)
|
* @dst: destination register (64 bit wide)
|
||||||
* @sym: name of the symbol
|
* @sym: name of the symbol
|
||||||
* @tmp: optional scratch register to be used if <dst> == sp, which
|
|
||||||
* is not allowed in an adrp instruction
|
|
||||||
*/
|
*/
|
||||||
.macro adr_l, dst, sym, tmp=
|
.macro adr_l, dst, sym
|
||||||
.ifb \tmp
|
#ifndef MODULE
|
||||||
adrp \dst, \sym
|
adrp \dst, \sym
|
||||||
add \dst, \dst, :lo12:\sym
|
add \dst, \dst, :lo12:\sym
|
||||||
.else
|
#else
|
||||||
adrp \tmp, \sym
|
movz \dst, #:abs_g3:\sym
|
||||||
add \dst, \tmp, :lo12:\sym
|
movk \dst, #:abs_g2_nc:\sym
|
||||||
.endif
|
movk \dst, #:abs_g1_nc:\sym
|
||||||
|
movk \dst, #:abs_g0_nc:\sym
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -190,6 +193,7 @@ lr .req x30 // link register
|
||||||
* the address
|
* the address
|
||||||
*/
|
*/
|
||||||
.macro ldr_l, dst, sym, tmp=
|
.macro ldr_l, dst, sym, tmp=
|
||||||
|
#ifndef MODULE
|
||||||
.ifb \tmp
|
.ifb \tmp
|
||||||
adrp \dst, \sym
|
adrp \dst, \sym
|
||||||
ldr \dst, [\dst, :lo12:\sym]
|
ldr \dst, [\dst, :lo12:\sym]
|
||||||
|
@ -197,6 +201,15 @@ lr .req x30 // link register
|
||||||
adrp \tmp, \sym
|
adrp \tmp, \sym
|
||||||
ldr \dst, [\tmp, :lo12:\sym]
|
ldr \dst, [\tmp, :lo12:\sym]
|
||||||
.endif
|
.endif
|
||||||
|
#else
|
||||||
|
.ifb \tmp
|
||||||
|
adr_l \dst, \sym
|
||||||
|
ldr \dst, [\dst]
|
||||||
|
.else
|
||||||
|
adr_l \tmp, \sym
|
||||||
|
ldr \dst, [\tmp]
|
||||||
|
.endif
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -206,8 +219,13 @@ lr .req x30 // link register
|
||||||
* while <src> needs to be preserved.
|
* while <src> needs to be preserved.
|
||||||
*/
|
*/
|
||||||
.macro str_l, src, sym, tmp
|
.macro str_l, src, sym, tmp
|
||||||
|
#ifndef MODULE
|
||||||
adrp \tmp, \sym
|
adrp \tmp, \sym
|
||||||
str \src, [\tmp, :lo12:\sym]
|
str \src, [\tmp, :lo12:\sym]
|
||||||
|
#else
|
||||||
|
adr_l \tmp, \sym
|
||||||
|
str \src, [\tmp]
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -239,7 +239,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||||
ncontig = find_num_contig(vma->vm_mm, addr, cpte,
|
ncontig = find_num_contig(vma->vm_mm, addr, cpte,
|
||||||
*cpte, &pgsize);
|
*cpte, &pgsize);
|
||||||
for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) {
|
for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) {
|
||||||
changed = ptep_set_access_flags(vma, addr, cpte,
|
changed |= ptep_set_access_flags(vma, addr, cpte,
|
||||||
pfn_pte(pfn,
|
pfn_pte(pfn,
|
||||||
hugeprot),
|
hugeprot),
|
||||||
dirty);
|
dirty);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include "ctype.h"
|
#include "ctype.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
int memcmp(const void *s1, const void *s2, size_t len)
|
int memcmp(const void *s1, const void *s2, size_t len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,4 +18,13 @@ int memcmp(const void *s1, const void *s2, size_t len);
|
||||||
#define memset(d,c,l) __builtin_memset(d,c,l)
|
#define memset(d,c,l) __builtin_memset(d,c,l)
|
||||||
#define memcmp __builtin_memcmp
|
#define memcmp __builtin_memcmp
|
||||||
|
|
||||||
|
extern int strcmp(const char *str1, const char *str2);
|
||||||
|
extern int strncmp(const char *cs, const char *ct, size_t count);
|
||||||
|
extern size_t strlen(const char *s);
|
||||||
|
extern char *strstr(const char *s1, const char *s2);
|
||||||
|
extern size_t strnlen(const char *s, size_t maxlen);
|
||||||
|
extern unsigned int atou(const char *s);
|
||||||
|
extern unsigned long long simple_strtoull(const char *cp, char **endp,
|
||||||
|
unsigned int base);
|
||||||
|
|
||||||
#endif /* BOOT_STRING_H */
|
#endif /* BOOT_STRING_H */
|
||||||
|
|
|
@ -254,23 +254,6 @@ ENTRY(__switch_to_asm)
|
||||||
jmp __switch_to
|
jmp __switch_to
|
||||||
END(__switch_to_asm)
|
END(__switch_to_asm)
|
||||||
|
|
||||||
/*
|
|
||||||
* The unwinder expects the last frame on the stack to always be at the same
|
|
||||||
* offset from the end of the page, which allows it to validate the stack.
|
|
||||||
* Calling schedule_tail() directly would break that convention because its an
|
|
||||||
* asmlinkage function so its argument has to be pushed on the stack. This
|
|
||||||
* wrapper creates a proper "end of stack" frame header before the call.
|
|
||||||
*/
|
|
||||||
ENTRY(schedule_tail_wrapper)
|
|
||||||
FRAME_BEGIN
|
|
||||||
|
|
||||||
pushl %eax
|
|
||||||
call schedule_tail
|
|
||||||
popl %eax
|
|
||||||
|
|
||||||
FRAME_END
|
|
||||||
ret
|
|
||||||
ENDPROC(schedule_tail_wrapper)
|
|
||||||
/*
|
/*
|
||||||
* A newly forked process directly context switches into this address.
|
* A newly forked process directly context switches into this address.
|
||||||
*
|
*
|
||||||
|
@ -279,15 +262,24 @@ ENDPROC(schedule_tail_wrapper)
|
||||||
* edi: kernel thread arg
|
* edi: kernel thread arg
|
||||||
*/
|
*/
|
||||||
ENTRY(ret_from_fork)
|
ENTRY(ret_from_fork)
|
||||||
call schedule_tail_wrapper
|
FRAME_BEGIN /* help unwinder find end of stack */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* schedule_tail() is asmlinkage so we have to put its 'prev' argument
|
||||||
|
* on the stack.
|
||||||
|
*/
|
||||||
|
pushl %eax
|
||||||
|
call schedule_tail
|
||||||
|
popl %eax
|
||||||
|
|
||||||
testl %ebx, %ebx
|
testl %ebx, %ebx
|
||||||
jnz 1f /* kernel threads are uncommon */
|
jnz 1f /* kernel threads are uncommon */
|
||||||
|
|
||||||
2:
|
2:
|
||||||
/* When we fork, we trace the syscall return in the child, too. */
|
/* When we fork, we trace the syscall return in the child, too. */
|
||||||
movl %esp, %eax
|
leal FRAME_OFFSET(%esp), %eax
|
||||||
call syscall_return_slowpath
|
call syscall_return_slowpath
|
||||||
|
FRAME_END
|
||||||
jmp restore_all
|
jmp restore_all
|
||||||
|
|
||||||
/* kernel thread */
|
/* kernel thread */
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <asm/smap.h>
|
#include <asm/smap.h>
|
||||||
#include <asm/pgtable_types.h>
|
#include <asm/pgtable_types.h>
|
||||||
#include <asm/export.h>
|
#include <asm/export.h>
|
||||||
|
#include <asm/frame.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
|
||||||
.code64
|
.code64
|
||||||
|
@ -408,17 +409,19 @@ END(__switch_to_asm)
|
||||||
* r12: kernel thread arg
|
* r12: kernel thread arg
|
||||||
*/
|
*/
|
||||||
ENTRY(ret_from_fork)
|
ENTRY(ret_from_fork)
|
||||||
|
FRAME_BEGIN /* help unwinder find end of stack */
|
||||||
movq %rax, %rdi
|
movq %rax, %rdi
|
||||||
call schedule_tail /* rdi: 'prev' task parameter */
|
call schedule_tail /* rdi: 'prev' task parameter */
|
||||||
|
|
||||||
testq %rbx, %rbx /* from kernel_thread? */
|
testq %rbx, %rbx /* from kernel_thread? */
|
||||||
jnz 1f /* kernel threads are uncommon */
|
jnz 1f /* kernel threads are uncommon */
|
||||||
|
|
||||||
2:
|
2:
|
||||||
movq %rsp, %rdi
|
leaq FRAME_OFFSET(%rsp),%rdi /* pt_regs pointer */
|
||||||
call syscall_return_slowpath /* returns with IRQs disabled */
|
call syscall_return_slowpath /* returns with IRQs disabled */
|
||||||
TRACE_IRQS_ON /* user mode is traced as IRQS on */
|
TRACE_IRQS_ON /* user mode is traced as IRQS on */
|
||||||
SWAPGS
|
SWAPGS
|
||||||
|
FRAME_END
|
||||||
jmp restore_regs_and_iret
|
jmp restore_regs_and_iret
|
||||||
|
|
||||||
1:
|
1:
|
||||||
|
|
|
@ -505,6 +505,10 @@ int x86_pmu_hw_config(struct perf_event *event)
|
||||||
|
|
||||||
if (event->attr.precise_ip > precise)
|
if (event->attr.precise_ip > precise)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* There's no sense in having PEBS for non sampling events: */
|
||||||
|
if (!is_sampling_event(event))
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* check that PEBS LBR correction does not conflict with
|
* check that PEBS LBR correction does not conflict with
|
||||||
|
|
|
@ -3987,7 +3987,7 @@ __init int intel_pmu_init(void)
|
||||||
x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
|
x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
|
||||||
x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
|
x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
|
||||||
}
|
}
|
||||||
x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
|
x86_pmu.intel_ctrl = (1ULL << x86_pmu.num_counters) - 1;
|
||||||
|
|
||||||
if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
|
if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
|
||||||
WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
|
WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
|
||||||
|
|
|
@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = {
|
||||||
.stop = cstate_pmu_event_stop,
|
.stop = cstate_pmu_event_stop,
|
||||||
.read = cstate_pmu_event_update,
|
.read = cstate_pmu_event_update,
|
||||||
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
||||||
|
.module = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pmu cstate_pkg_pmu = {
|
static struct pmu cstate_pkg_pmu = {
|
||||||
|
@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = {
|
||||||
.stop = cstate_pmu_event_stop,
|
.stop = cstate_pmu_event_stop,
|
||||||
.read = cstate_pmu_event_update,
|
.read = cstate_pmu_event_update,
|
||||||
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
||||||
|
.module = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct cstate_model nhm_cstates __initconst = {
|
static const struct cstate_model nhm_cstates __initconst = {
|
||||||
|
|
|
@ -1389,9 +1389,13 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* log dropped samples number */
|
/* log dropped samples number */
|
||||||
if (error[bit])
|
if (error[bit]) {
|
||||||
perf_log_lost_samples(event, error[bit]);
|
perf_log_lost_samples(event, error[bit]);
|
||||||
|
|
||||||
|
if (perf_event_account_interrupt(event))
|
||||||
|
x86_pmu_stop(event, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (counts[bit]) {
|
if (counts[bit]) {
|
||||||
__intel_pmu_pebs_event(event, iregs, base,
|
__intel_pmu_pebs_event(event, iregs, base,
|
||||||
top, bit, counts[bit]);
|
top, bit, counts[bit]);
|
||||||
|
|
|
@ -697,6 +697,7 @@ static int __init init_rapl_pmus(void)
|
||||||
rapl_pmus->pmu.start = rapl_pmu_event_start;
|
rapl_pmus->pmu.start = rapl_pmu_event_start;
|
||||||
rapl_pmus->pmu.stop = rapl_pmu_event_stop;
|
rapl_pmus->pmu.stop = rapl_pmu_event_stop;
|
||||||
rapl_pmus->pmu.read = rapl_pmu_event_read;
|
rapl_pmus->pmu.read = rapl_pmu_event_read;
|
||||||
|
rapl_pmus->pmu.module = THIS_MODULE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -733,6 +733,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
|
||||||
.start = uncore_pmu_event_start,
|
.start = uncore_pmu_event_start,
|
||||||
.stop = uncore_pmu_event_stop,
|
.stop = uncore_pmu_event_stop,
|
||||||
.read = uncore_pmu_event_read,
|
.read = uncore_pmu_event_read,
|
||||||
|
.module = THIS_MODULE,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
pmu->pmu = *pmu->type->pmu;
|
pmu->pmu = *pmu->type->pmu;
|
||||||
|
|
|
@ -2686,7 +2686,7 @@ static struct intel_uncore_type *hswep_msr_uncores[] = {
|
||||||
|
|
||||||
void hswep_uncore_cpu_init(void)
|
void hswep_uncore_cpu_init(void)
|
||||||
{
|
{
|
||||||
int pkg = topology_phys_to_logical_pkg(0);
|
int pkg = boot_cpu_data.logical_proc_id;
|
||||||
|
|
||||||
if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
|
if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
|
||||||
hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
|
hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */
|
#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */
|
||||||
#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */
|
#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */
|
||||||
#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
|
#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
|
||||||
#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Annidale */
|
#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */
|
||||||
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C
|
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C
|
||||||
#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
|
#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,21 @@ struct extended_sigtable {
|
||||||
|
|
||||||
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
|
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
|
||||||
|
|
||||||
|
static inline u32 intel_get_microcode_revision(void)
|
||||||
|
{
|
||||||
|
u32 rev, dummy;
|
||||||
|
|
||||||
|
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
|
||||||
|
|
||||||
|
/* As documented in the SDM: Do a CPUID 1 here */
|
||||||
|
native_cpuid_eax(1);
|
||||||
|
|
||||||
|
/* get the current revision from MSR 0x8B */
|
||||||
|
native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev);
|
||||||
|
|
||||||
|
return rev;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MICROCODE_INTEL
|
#ifdef CONFIG_MICROCODE_INTEL
|
||||||
extern void __init load_ucode_intel_bsp(void);
|
extern void __init load_ucode_intel_bsp(void);
|
||||||
extern void load_ucode_intel_ap(void);
|
extern void load_ucode_intel_ap(void);
|
||||||
|
|
|
@ -219,6 +219,24 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define native_cpuid_reg(reg) \
|
||||||
|
static inline unsigned int native_cpuid_##reg(unsigned int op) \
|
||||||
|
{ \
|
||||||
|
unsigned int eax = op, ebx, ecx = 0, edx; \
|
||||||
|
\
|
||||||
|
native_cpuid(&eax, &ebx, &ecx, &edx); \
|
||||||
|
\
|
||||||
|
return reg; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Native CPUID functions returning a single datum.
|
||||||
|
*/
|
||||||
|
native_cpuid_reg(eax)
|
||||||
|
native_cpuid_reg(ebx)
|
||||||
|
native_cpuid_reg(ecx)
|
||||||
|
native_cpuid_reg(edx)
|
||||||
|
|
||||||
static inline void load_cr3(pgd_t *pgdir)
|
static inline void load_cr3(pgd_t *pgdir)
|
||||||
{
|
{
|
||||||
write_cr3(__pa(pgdir));
|
write_cr3(__pa(pgdir));
|
||||||
|
|
|
@ -58,7 +58,7 @@ get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
|
||||||
if (task == current)
|
if (task == current)
|
||||||
return __builtin_frame_address(0);
|
return __builtin_frame_address(0);
|
||||||
|
|
||||||
return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
|
return &((struct inactive_task_frame *)task->thread.sp)->bp;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline unsigned long *
|
static inline unsigned long *
|
||||||
|
|
|
@ -36,7 +36,10 @@ static inline void prepare_switch_to(struct task_struct *prev,
|
||||||
|
|
||||||
asmlinkage void ret_from_fork(void);
|
asmlinkage void ret_from_fork(void);
|
||||||
|
|
||||||
/* data that is pointed to by thread.sp */
|
/*
|
||||||
|
* This is the structure pointed to by thread.sp for an inactive task. The
|
||||||
|
* order of the fields must match the code in __switch_to_asm().
|
||||||
|
*/
|
||||||
struct inactive_task_frame {
|
struct inactive_task_frame {
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
unsigned long r15;
|
unsigned long r15;
|
||||||
|
@ -48,6 +51,11 @@ struct inactive_task_frame {
|
||||||
unsigned long di;
|
unsigned long di;
|
||||||
#endif
|
#endif
|
||||||
unsigned long bx;
|
unsigned long bx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These two fields must be together. They form a stack frame header,
|
||||||
|
* needed by get_frame_pointer().
|
||||||
|
*/
|
||||||
unsigned long bp;
|
unsigned long bp;
|
||||||
unsigned long ret_addr;
|
unsigned long ret_addr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -309,15 +309,8 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
|
||||||
|
|
||||||
/* get information required for multi-node processors */
|
/* get information required for multi-node processors */
|
||||||
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
|
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
|
||||||
u32 eax, ebx, ecx, edx;
|
|
||||||
|
|
||||||
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
|
node_id = cpuid_ecx(0x8000001e) & 7;
|
||||||
node_id = ecx & 7;
|
|
||||||
|
|
||||||
/* get compute unit information */
|
|
||||||
smp_num_siblings = ((ebx >> 8) & 3) + 1;
|
|
||||||
c->x86_max_cores /= smp_num_siblings;
|
|
||||||
c->cpu_core_id = ebx & 0xff;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may have multiple LLCs if L3 caches exist, so check if we
|
* We may have multiple LLCs if L3 caches exist, so check if we
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ static __init int setup_disablecpuid(char *arg)
|
||||||
{
|
{
|
||||||
int bit;
|
int bit;
|
||||||
|
|
||||||
if (get_option(&arg, &bit) && bit < NCAPINTS*32)
|
if (get_option(&arg, &bit) && bit >= 0 && bit < NCAPINTS * 32)
|
||||||
setup_clear_cpu_cap(bit);
|
setup_clear_cpu_cap(bit);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <asm/bugs.h>
|
#include <asm/bugs.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
#include <asm/intel-family.h>
|
#include <asm/intel-family.h>
|
||||||
|
#include <asm/microcode_intel.h>
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
#include <linux/topology.h>
|
#include <linux/topology.h>
|
||||||
|
@ -78,14 +79,8 @@ static void early_init_intel(struct cpuinfo_x86 *c)
|
||||||
(c->x86 == 0x6 && c->x86_model >= 0x0e))
|
(c->x86 == 0x6 && c->x86_model >= 0x0e))
|
||||||
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
||||||
|
|
||||||
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
|
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
|
||||||
unsigned lower_word;
|
c->microcode = intel_get_microcode_revision();
|
||||||
|
|
||||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
|
||||||
/* Required by the SDM */
|
|
||||||
sync_core();
|
|
||||||
rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atom erratum AAE44/AAF40/AAG38/AAH41:
|
* Atom erratum AAE44/AAF40/AAG38/AAH41:
|
||||||
|
|
|
@ -150,7 +150,7 @@ static struct ucode_patch *__alloc_microcode_buf(void *data, unsigned int size)
|
||||||
{
|
{
|
||||||
struct ucode_patch *p;
|
struct ucode_patch *p;
|
||||||
|
|
||||||
p = kzalloc(size, GFP_KERNEL);
|
p = kzalloc(sizeof(struct ucode_patch), GFP_KERNEL);
|
||||||
if (!p)
|
if (!p)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
@ -368,26 +368,6 @@ next:
|
||||||
return patch;
|
return patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpuid_1(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* According to the Intel SDM, Volume 3, 9.11.7:
|
|
||||||
*
|
|
||||||
* CPUID returns a value in a model specific register in
|
|
||||||
* addition to its usual register return values. The
|
|
||||||
* semantics of CPUID cause it to deposit an update ID value
|
|
||||||
* in the 64-bit model-specific register at address 08BH
|
|
||||||
* (IA32_BIOS_SIGN_ID). If no update is present in the
|
|
||||||
* processor, the value in the MSR remains unmodified.
|
|
||||||
*
|
|
||||||
* Use native_cpuid -- this code runs very early and we don't
|
|
||||||
* want to mess with paravirt.
|
|
||||||
*/
|
|
||||||
unsigned int eax = 1, ebx, ecx = 0, edx;
|
|
||||||
|
|
||||||
native_cpuid(&eax, &ebx, &ecx, &edx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int collect_cpu_info_early(struct ucode_cpu_info *uci)
|
static int collect_cpu_info_early(struct ucode_cpu_info *uci)
|
||||||
{
|
{
|
||||||
unsigned int val[2];
|
unsigned int val[2];
|
||||||
|
@ -410,15 +390,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
|
||||||
native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
|
native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
|
||||||
csig.pf = 1 << ((val[1] >> 18) & 7);
|
csig.pf = 1 << ((val[1] >> 18) & 7);
|
||||||
}
|
}
|
||||||
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
|
|
||||||
|
|
||||||
/* As documented in the SDM: Do a CPUID 1 here */
|
csig.rev = intel_get_microcode_revision();
|
||||||
cpuid_1();
|
|
||||||
|
|
||||||
/* get the current revision from MSR 0x8B */
|
|
||||||
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
|
||||||
|
|
||||||
csig.rev = val[1];
|
|
||||||
|
|
||||||
uci->cpu_sig = csig;
|
uci->cpu_sig = csig;
|
||||||
uci->valid = 1;
|
uci->valid = 1;
|
||||||
|
@ -602,7 +575,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci)
|
||||||
static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||||||
{
|
{
|
||||||
struct microcode_intel *mc;
|
struct microcode_intel *mc;
|
||||||
unsigned int val[2];
|
u32 rev;
|
||||||
|
|
||||||
mc = uci->mc;
|
mc = uci->mc;
|
||||||
if (!mc)
|
if (!mc)
|
||||||
|
@ -610,21 +583,16 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||||||
|
|
||||||
/* write microcode via MSR 0x79 */
|
/* write microcode via MSR 0x79 */
|
||||||
native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
||||||
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
|
|
||||||
|
|
||||||
/* As documented in the SDM: Do a CPUID 1 here */
|
rev = intel_get_microcode_revision();
|
||||||
cpuid_1();
|
if (rev != mc->hdr.rev)
|
||||||
|
|
||||||
/* get the current revision from MSR 0x8B */
|
|
||||||
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
|
||||||
if (val[1] != mc->hdr.rev)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
/* Flush global tlb. This is precaution. */
|
/* Flush global tlb. This is precaution. */
|
||||||
flush_tlb_early();
|
flush_tlb_early();
|
||||||
#endif
|
#endif
|
||||||
uci->cpu_sig.rev = val[1];
|
uci->cpu_sig.rev = rev;
|
||||||
|
|
||||||
if (early)
|
if (early)
|
||||||
print_ucode(uci);
|
print_ucode(uci);
|
||||||
|
@ -804,8 +772,8 @@ static int apply_microcode_intel(int cpu)
|
||||||
struct microcode_intel *mc;
|
struct microcode_intel *mc;
|
||||||
struct ucode_cpu_info *uci;
|
struct ucode_cpu_info *uci;
|
||||||
struct cpuinfo_x86 *c;
|
struct cpuinfo_x86 *c;
|
||||||
unsigned int val[2];
|
|
||||||
static int prev_rev;
|
static int prev_rev;
|
||||||
|
u32 rev;
|
||||||
|
|
||||||
/* We should bind the task to the CPU */
|
/* We should bind the task to the CPU */
|
||||||
if (WARN_ON(raw_smp_processor_id() != cpu))
|
if (WARN_ON(raw_smp_processor_id() != cpu))
|
||||||
|
@ -822,33 +790,28 @@ static int apply_microcode_intel(int cpu)
|
||||||
|
|
||||||
/* write microcode via MSR 0x79 */
|
/* write microcode via MSR 0x79 */
|
||||||
wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
||||||
wrmsrl(MSR_IA32_UCODE_REV, 0);
|
|
||||||
|
|
||||||
/* As documented in the SDM: Do a CPUID 1 here */
|
rev = intel_get_microcode_revision();
|
||||||
cpuid_1();
|
|
||||||
|
|
||||||
/* get the current revision from MSR 0x8B */
|
if (rev != mc->hdr.rev) {
|
||||||
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
|
||||||
|
|
||||||
if (val[1] != mc->hdr.rev) {
|
|
||||||
pr_err("CPU%d update to revision 0x%x failed\n",
|
pr_err("CPU%d update to revision 0x%x failed\n",
|
||||||
cpu, mc->hdr.rev);
|
cpu, mc->hdr.rev);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val[1] != prev_rev) {
|
if (rev != prev_rev) {
|
||||||
pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
|
pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
|
||||||
val[1],
|
rev,
|
||||||
mc->hdr.date & 0xffff,
|
mc->hdr.date & 0xffff,
|
||||||
mc->hdr.date >> 24,
|
mc->hdr.date >> 24,
|
||||||
(mc->hdr.date >> 16) & 0xff);
|
(mc->hdr.date >> 16) & 0xff);
|
||||||
prev_rev = val[1];
|
prev_rev = rev;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = &cpu_data(cpu);
|
c = &cpu_data(cpu);
|
||||||
|
|
||||||
uci->cpu_sig.rev = val[1];
|
uci->cpu_sig.rev = rev;
|
||||||
c->microcode = val[1];
|
c->microcode = rev;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -860,7 +823,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
||||||
u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
|
u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
|
||||||
int new_rev = uci->cpu_sig.rev;
|
int new_rev = uci->cpu_sig.rev;
|
||||||
unsigned int leftover = size;
|
unsigned int leftover = size;
|
||||||
unsigned int curr_mc_size = 0;
|
unsigned int curr_mc_size = 0, new_mc_size = 0;
|
||||||
unsigned int csig, cpf;
|
unsigned int csig, cpf;
|
||||||
|
|
||||||
while (leftover) {
|
while (leftover) {
|
||||||
|
@ -901,6 +864,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
||||||
vfree(new_mc);
|
vfree(new_mc);
|
||||||
new_rev = mc_header.rev;
|
new_rev = mc_header.rev;
|
||||||
new_mc = mc;
|
new_mc = mc;
|
||||||
|
new_mc_size = mc_size;
|
||||||
mc = NULL; /* trigger new vmalloc */
|
mc = NULL; /* trigger new vmalloc */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,7 +890,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
||||||
* permanent memory. So it will be loaded early when a CPU is hot added
|
* permanent memory. So it will be loaded early when a CPU is hot added
|
||||||
* or resumes.
|
* or resumes.
|
||||||
*/
|
*/
|
||||||
save_mc_for_early(new_mc, curr_mc_size);
|
save_mc_for_early(new_mc, new_mc_size);
|
||||||
|
|
||||||
pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
|
pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
|
||||||
cpu, new_rev, uci->cpu_sig.rev);
|
cpu, new_rev, uci->cpu_sig.rev);
|
||||||
|
|
|
@ -694,6 +694,7 @@ unsigned long native_calibrate_tsc(void)
|
||||||
crystal_khz = 24000; /* 24.0 MHz */
|
crystal_khz = 24000; /* 24.0 MHz */
|
||||||
break;
|
break;
|
||||||
case INTEL_FAM6_SKYLAKE_X:
|
case INTEL_FAM6_SKYLAKE_X:
|
||||||
|
case INTEL_FAM6_ATOM_DENVERTON:
|
||||||
crystal_khz = 25000; /* 25.0 MHz */
|
crystal_khz = 25000; /* 25.0 MHz */
|
||||||
break;
|
break;
|
||||||
case INTEL_FAM6_ATOM_GOLDMONT:
|
case INTEL_FAM6_ATOM_GOLDMONT:
|
||||||
|
|
|
@ -6,6 +6,21 @@
|
||||||
|
|
||||||
#define FRAME_HEADER_SIZE (sizeof(long) * 2)
|
#define FRAME_HEADER_SIZE (sizeof(long) * 2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This disables KASAN checking when reading a value from another task's stack,
|
||||||
|
* since the other task could be running on another CPU and could have poisoned
|
||||||
|
* the stack in the meantime.
|
||||||
|
*/
|
||||||
|
#define READ_ONCE_TASK_STACK(task, x) \
|
||||||
|
({ \
|
||||||
|
unsigned long val; \
|
||||||
|
if (task == current) \
|
||||||
|
val = READ_ONCE(x); \
|
||||||
|
else \
|
||||||
|
val = READ_ONCE_NOCHECK(x); \
|
||||||
|
val; \
|
||||||
|
})
|
||||||
|
|
||||||
static void unwind_dump(struct unwind_state *state, unsigned long *sp)
|
static void unwind_dump(struct unwind_state *state, unsigned long *sp)
|
||||||
{
|
{
|
||||||
static bool dumped_before = false;
|
static bool dumped_before = false;
|
||||||
|
@ -48,7 +63,8 @@ unsigned long unwind_get_return_address(struct unwind_state *state)
|
||||||
if (state->regs && user_mode(state->regs))
|
if (state->regs && user_mode(state->regs))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, *addr_p,
|
addr = READ_ONCE_TASK_STACK(state->task, *addr_p);
|
||||||
|
addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr,
|
||||||
addr_p);
|
addr_p);
|
||||||
|
|
||||||
return __kernel_text_address(addr) ? addr : 0;
|
return __kernel_text_address(addr) ? addr : 0;
|
||||||
|
@ -162,7 +178,7 @@ bool unwind_next_frame(struct unwind_state *state)
|
||||||
if (state->regs)
|
if (state->regs)
|
||||||
next_bp = (unsigned long *)state->regs->bp;
|
next_bp = (unsigned long *)state->regs->bp;
|
||||||
else
|
else
|
||||||
next_bp = (unsigned long *)*state->bp;
|
next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task,*state->bp);
|
||||||
|
|
||||||
/* is the next frame pointer an encoded pointer to pt_regs? */
|
/* is the next frame pointer an encoded pointer to pt_regs? */
|
||||||
regs = decode_frame_pointer(next_bp);
|
regs = decode_frame_pointer(next_bp);
|
||||||
|
@ -207,6 +223,16 @@ bool unwind_next_frame(struct unwind_state *state)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bad_address:
|
bad_address:
|
||||||
|
/*
|
||||||
|
* When unwinding a non-current task, the task might actually be
|
||||||
|
* running on another CPU, in which case it could be modifying its
|
||||||
|
* stack while we're reading it. This is generally not a problem and
|
||||||
|
* can be ignored as long as the caller understands that unwinding
|
||||||
|
* another task will not always succeed.
|
||||||
|
*/
|
||||||
|
if (state->task != current)
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
if (state->regs) {
|
if (state->regs) {
|
||||||
printk_deferred_once(KERN_WARNING
|
printk_deferred_once(KERN_WARNING
|
||||||
"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
|
"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
|
||||||
|
|
|
@ -818,6 +818,20 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
|
||||||
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
|
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
|
||||||
|
struct segmented_address addr,
|
||||||
|
void *data,
|
||||||
|
unsigned int size)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
ulong linear;
|
||||||
|
|
||||||
|
rc = linearize(ctxt, addr, size, true, &linear);
|
||||||
|
if (rc != X86EMUL_CONTINUE)
|
||||||
|
return rc;
|
||||||
|
return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prefetch the remaining bytes of the instruction without crossing page
|
* Prefetch the remaining bytes of the instruction without crossing page
|
||||||
* boundary if they are not in fetch_cache yet.
|
* boundary if they are not in fetch_cache yet.
|
||||||
|
@ -1571,7 +1585,6 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
&ctxt->exception);
|
&ctxt->exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does not support long mode */
|
|
||||||
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
u16 selector, int seg, u8 cpl,
|
u16 selector, int seg, u8 cpl,
|
||||||
enum x86_transfer_type transfer,
|
enum x86_transfer_type transfer,
|
||||||
|
@ -1608,20 +1621,34 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
|
|
||||||
rpl = selector & 3;
|
rpl = selector & 3;
|
||||||
|
|
||||||
/* NULL selector is not valid for TR, CS and SS (except for long mode) */
|
|
||||||
if ((seg == VCPU_SREG_CS
|
|
||||||
|| (seg == VCPU_SREG_SS
|
|
||||||
&& (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl))
|
|
||||||
|| seg == VCPU_SREG_TR)
|
|
||||||
&& null_selector)
|
|
||||||
goto exception;
|
|
||||||
|
|
||||||
/* TR should be in GDT only */
|
/* TR should be in GDT only */
|
||||||
if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
|
if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
|
||||||
goto exception;
|
goto exception;
|
||||||
|
|
||||||
if (null_selector) /* for NULL selector skip all following checks */
|
/* NULL selector is not valid for TR, CS and (except for long mode) SS */
|
||||||
|
if (null_selector) {
|
||||||
|
if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR)
|
||||||
|
goto exception;
|
||||||
|
|
||||||
|
if (seg == VCPU_SREG_SS) {
|
||||||
|
if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)
|
||||||
|
goto exception;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ctxt->ops->set_segment expects the CPL to be in
|
||||||
|
* SS.DPL, so fake an expand-up 32-bit data segment.
|
||||||
|
*/
|
||||||
|
seg_desc.type = 3;
|
||||||
|
seg_desc.p = 1;
|
||||||
|
seg_desc.s = 1;
|
||||||
|
seg_desc.dpl = cpl;
|
||||||
|
seg_desc.d = 1;
|
||||||
|
seg_desc.g = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip all following checks */
|
||||||
goto load;
|
goto load;
|
||||||
|
}
|
||||||
|
|
||||||
ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
|
ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
|
||||||
if (ret != X86EMUL_CONTINUE)
|
if (ret != X86EMUL_CONTINUE)
|
||||||
|
@ -1737,6 +1764,21 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
u16 selector, int seg)
|
u16 selector, int seg)
|
||||||
{
|
{
|
||||||
u8 cpl = ctxt->ops->cpl(ctxt);
|
u8 cpl = ctxt->ops->cpl(ctxt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* None of MOV, POP and LSS can load a NULL selector in CPL=3, but
|
||||||
|
* they can load it at CPL<3 (Intel's manual says only LSS can,
|
||||||
|
* but it's wrong).
|
||||||
|
*
|
||||||
|
* However, the Intel manual says that putting IST=1/DPL=3 in
|
||||||
|
* an interrupt gate will result in SS=3 (the AMD manual instead
|
||||||
|
* says it doesn't), so allow SS=3 in __load_segment_descriptor
|
||||||
|
* and only forbid it here.
|
||||||
|
*/
|
||||||
|
if (seg == VCPU_SREG_SS && selector == 3 &&
|
||||||
|
ctxt->mode == X86EMUL_MODE_PROT64)
|
||||||
|
return emulate_exception(ctxt, GP_VECTOR, 0, true);
|
||||||
|
|
||||||
return __load_segment_descriptor(ctxt, selector, seg, cpl,
|
return __load_segment_descriptor(ctxt, selector, seg, cpl,
|
||||||
X86_TRANSFER_NONE, NULL);
|
X86_TRANSFER_NONE, NULL);
|
||||||
}
|
}
|
||||||
|
@ -3685,8 +3727,8 @@ static int emulate_store_desc_ptr(struct x86_emulate_ctxt *ctxt,
|
||||||
}
|
}
|
||||||
/* Disable writeback. */
|
/* Disable writeback. */
|
||||||
ctxt->dst.type = OP_NONE;
|
ctxt->dst.type = OP_NONE;
|
||||||
return segmented_write(ctxt, ctxt->dst.addr.mem,
|
return segmented_write_std(ctxt, ctxt->dst.addr.mem,
|
||||||
&desc_ptr, 2 + ctxt->op_bytes);
|
&desc_ptr, 2 + ctxt->op_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int em_sgdt(struct x86_emulate_ctxt *ctxt)
|
static int em_sgdt(struct x86_emulate_ctxt *ctxt)
|
||||||
|
@ -3932,7 +3974,7 @@ static int em_fxsave(struct x86_emulate_ctxt *ctxt)
|
||||||
else
|
else
|
||||||
size = offsetof(struct fxregs_state, xmm_space[0]);
|
size = offsetof(struct fxregs_state, xmm_space[0]);
|
||||||
|
|
||||||
return segmented_write(ctxt, ctxt->memop.addr.mem, &fx_state, size);
|
return segmented_write_std(ctxt, ctxt->memop.addr.mem, &fx_state, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
|
static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
|
||||||
|
@ -3974,7 +4016,7 @@ static int em_fxrstor(struct x86_emulate_ctxt *ctxt)
|
||||||
if (rc != X86EMUL_CONTINUE)
|
if (rc != X86EMUL_CONTINUE)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = segmented_read(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
|
rc = segmented_read_std(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
|
||||||
if (rc != X86EMUL_CONTINUE)
|
if (rc != X86EMUL_CONTINUE)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
|
|
@ -2426,3 +2426,9 @@ void kvm_lapic_init(void)
|
||||||
jump_label_rate_limit(&apic_hw_disabled, HZ);
|
jump_label_rate_limit(&apic_hw_disabled, HZ);
|
||||||
jump_label_rate_limit(&apic_sw_disabled, HZ);
|
jump_label_rate_limit(&apic_sw_disabled, HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kvm_lapic_exit(void)
|
||||||
|
{
|
||||||
|
static_key_deferred_flush(&apic_hw_disabled);
|
||||||
|
static_key_deferred_flush(&apic_sw_disabled);
|
||||||
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
|
int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
|
||||||
void kvm_lapic_init(void);
|
void kvm_lapic_init(void);
|
||||||
|
void kvm_lapic_exit(void);
|
||||||
|
|
||||||
#define VEC_POS(v) ((v) & (32 - 1))
|
#define VEC_POS(v) ((v) & (32 - 1))
|
||||||
#define REG_POS(v) (((v) >> 5) << 4)
|
#define REG_POS(v) (((v) >> 5) << 4)
|
||||||
|
|
|
@ -3342,6 +3342,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
|
||||||
|
|
||||||
switch (cap->cap) {
|
switch (cap->cap) {
|
||||||
case KVM_CAP_HYPERV_SYNIC:
|
case KVM_CAP_HYPERV_SYNIC:
|
||||||
|
if (!irqchip_in_kernel(vcpu->kvm))
|
||||||
|
return -EINVAL;
|
||||||
return kvm_hv_activate_synic(vcpu);
|
return kvm_hv_activate_synic(vcpu);
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -6045,6 +6047,7 @@ out:
|
||||||
|
|
||||||
void kvm_arch_exit(void)
|
void kvm_arch_exit(void)
|
||||||
{
|
{
|
||||||
|
kvm_lapic_exit();
|
||||||
perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
|
perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
|
||||||
|
|
||||||
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
|
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
|
||||||
|
|
|
@ -293,7 +293,7 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs)
|
||||||
* We were not able to extract an address from the instruction,
|
* We were not able to extract an address from the instruction,
|
||||||
* probably because there was something invalid in it.
|
* probably because there was something invalid in it.
|
||||||
*/
|
*/
|
||||||
if (info->si_addr == (void *)-1) {
|
if (info->si_addr == (void __user *)-1) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,6 +210,70 @@ int __init efi_memblock_x86_reserve_range(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define OVERFLOW_ADDR_SHIFT (64 - EFI_PAGE_SHIFT)
|
||||||
|
#define OVERFLOW_ADDR_MASK (U64_MAX << OVERFLOW_ADDR_SHIFT)
|
||||||
|
#define U64_HIGH_BIT (~(U64_MAX >> 1))
|
||||||
|
|
||||||
|
static bool __init efi_memmap_entry_valid(const efi_memory_desc_t *md, int i)
|
||||||
|
{
|
||||||
|
u64 end = (md->num_pages << EFI_PAGE_SHIFT) + md->phys_addr - 1;
|
||||||
|
u64 end_hi = 0;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
if (md->num_pages == 0) {
|
||||||
|
end = 0;
|
||||||
|
} else if (md->num_pages > EFI_PAGES_MAX ||
|
||||||
|
EFI_PAGES_MAX - md->num_pages <
|
||||||
|
(md->phys_addr >> EFI_PAGE_SHIFT)) {
|
||||||
|
end_hi = (md->num_pages & OVERFLOW_ADDR_MASK)
|
||||||
|
>> OVERFLOW_ADDR_SHIFT;
|
||||||
|
|
||||||
|
if ((md->phys_addr & U64_HIGH_BIT) && !(end & U64_HIGH_BIT))
|
||||||
|
end_hi += 1;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_warn_once(FW_BUG "Invalid EFI memory map entries:\n");
|
||||||
|
|
||||||
|
if (end_hi) {
|
||||||
|
pr_warn("mem%02u: %s range=[0x%016llx-0x%llx%016llx] (invalid)\n",
|
||||||
|
i, efi_md_typeattr_format(buf, sizeof(buf), md),
|
||||||
|
md->phys_addr, end_hi, end);
|
||||||
|
} else {
|
||||||
|
pr_warn("mem%02u: %s range=[0x%016llx-0x%016llx] (invalid)\n",
|
||||||
|
i, efi_md_typeattr_format(buf, sizeof(buf), md),
|
||||||
|
md->phys_addr, end);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init efi_clean_memmap(void)
|
||||||
|
{
|
||||||
|
efi_memory_desc_t *out = efi.memmap.map;
|
||||||
|
const efi_memory_desc_t *in = out;
|
||||||
|
const efi_memory_desc_t *end = efi.memmap.map_end;
|
||||||
|
int i, n_removal;
|
||||||
|
|
||||||
|
for (i = n_removal = 0; in < end; i++) {
|
||||||
|
if (efi_memmap_entry_valid(in, i)) {
|
||||||
|
if (out != in)
|
||||||
|
memcpy(out, in, efi.memmap.desc_size);
|
||||||
|
out = (void *)out + efi.memmap.desc_size;
|
||||||
|
} else {
|
||||||
|
n_removal++;
|
||||||
|
}
|
||||||
|
in = (void *)in + efi.memmap.desc_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_removal > 0) {
|
||||||
|
u64 size = efi.memmap.nr_map - n_removal;
|
||||||
|
|
||||||
|
pr_warn("Removing %d invalid memory map entries.\n", n_removal);
|
||||||
|
efi_memmap_install(efi.memmap.phys_map, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void __init efi_print_memmap(void)
|
void __init efi_print_memmap(void)
|
||||||
{
|
{
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
|
@ -472,6 +536,8 @@ void __init efi_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
efi_clean_memmap();
|
||||||
|
|
||||||
if (efi_enabled(EFI_DBG))
|
if (efi_enabled(EFI_DBG))
|
||||||
efi_print_memmap();
|
efi_print_memmap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
|
||||||
|
|
||||||
new_size = efi.memmap.desc_size * num_entries;
|
new_size = efi.memmap.desc_size * num_entries;
|
||||||
|
|
||||||
new_phys = memblock_alloc(new_size, 0);
|
new_phys = efi_memmap_alloc(num_entries);
|
||||||
if (!new_phys) {
|
if (!new_phys) {
|
||||||
pr_err("Could not allocate boot services memmap\n");
|
pr_err("Could not allocate boot services memmap\n");
|
||||||
return;
|
return;
|
||||||
|
@ -355,7 +355,7 @@ void __init efi_free_boot_services(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
new_size = efi.memmap.desc_size * num_entries;
|
new_size = efi.memmap.desc_size * num_entries;
|
||||||
new_phys = memblock_alloc(new_size, 0);
|
new_phys = efi_memmap_alloc(num_entries);
|
||||||
if (!new_phys) {
|
if (!new_phys) {
|
||||||
pr_err("Failed to allocate new EFI memmap\n");
|
pr_err("Failed to allocate new EFI memmap\n");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -15,7 +15,7 @@ obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_msic_power_btn.o
|
||||||
obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
|
obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
|
||||||
obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
|
obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
|
||||||
# SPI Devices
|
# SPI Devices
|
||||||
obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_spidev.o
|
obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_mrfld_spidev.o
|
||||||
# I2C Devices
|
# I2C Devices
|
||||||
obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
|
obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
|
||||||
obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
|
obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
* of the License.
|
* of the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/err.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/sfi.h>
|
#include <linux/sfi.h>
|
||||||
#include <linux/spi/pxa2xx_spi.h>
|
#include <linux/spi/pxa2xx_spi.h>
|
||||||
|
@ -34,6 +35,9 @@ static void __init *spidev_platform_data(void *info)
|
||||||
{
|
{
|
||||||
struct spi_board_info *spi_info = info;
|
struct spi_board_info *spi_info = info;
|
||||||
|
|
||||||
|
if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
spi_info->mode = SPI_MODE_0;
|
spi_info->mode = SPI_MODE_0;
|
||||||
spi_info->controller_data = &spidev_spi_chip;
|
spi_info->controller_data = &spidev_spi_chip;
|
||||||
|
|
|
@ -301,13 +301,6 @@ int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
|
||||||
if ((sector | nr_sects) & bs_mask)
|
if ((sector | nr_sects) & bs_mask)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (discard) {
|
|
||||||
ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
|
|
||||||
BLKDEV_DISCARD_ZERO, biop);
|
|
||||||
if (ret == 0 || (ret && ret != -EOPNOTSUPP))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
|
ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
|
||||||
biop);
|
biop);
|
||||||
if (ret == 0 || (ret && ret != -EOPNOTSUPP))
|
if (ret == 0 || (ret && ret != -EOPNOTSUPP))
|
||||||
|
@ -370,6 +363,12 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
|
||||||
struct bio *bio = NULL;
|
struct bio *bio = NULL;
|
||||||
struct blk_plug plug;
|
struct blk_plug plug;
|
||||||
|
|
||||||
|
if (discard) {
|
||||||
|
if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
|
||||||
|
BLKDEV_DISCARD_ZERO))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
blk_start_plug(&plug);
|
blk_start_plug(&plug);
|
||||||
ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
|
ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
|
||||||
&bio, discard);
|
&bio, discard);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
static inline sector_t blk_zone_start(struct request_queue *q,
|
static inline sector_t blk_zone_start(struct request_queue *q,
|
||||||
sector_t sector)
|
sector_t sector)
|
||||||
{
|
{
|
||||||
sector_t zone_mask = blk_queue_zone_size(q) - 1;
|
sector_t zone_mask = blk_queue_zone_sectors(q) - 1;
|
||||||
|
|
||||||
return sector & ~zone_mask;
|
return sector & ~zone_mask;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ int blkdev_reset_zones(struct block_device *bdev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Check alignment (handle eventual smaller last zone) */
|
/* Check alignment (handle eventual smaller last zone) */
|
||||||
zone_sectors = blk_queue_zone_size(q);
|
zone_sectors = blk_queue_zone_sectors(q);
|
||||||
if (sector & (zone_sectors - 1))
|
if (sector & (zone_sectors - 1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,7 @@ static bool part_zone_aligned(struct gendisk *disk,
|
||||||
struct block_device *bdev,
|
struct block_device *bdev,
|
||||||
sector_t from, sector_t size)
|
sector_t from, sector_t size)
|
||||||
{
|
{
|
||||||
unsigned int zone_size = bdev_zone_size(bdev);
|
unsigned int zone_sectors = bdev_zone_sectors(bdev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this function is called, then the disk is a zoned block device
|
* If this function is called, then the disk is a zoned block device
|
||||||
|
@ -446,7 +446,7 @@ static bool part_zone_aligned(struct gendisk *disk,
|
||||||
* regular block devices (no zone operation) and their zone size will
|
* regular block devices (no zone operation) and their zone size will
|
||||||
* be reported as 0. Allow this case.
|
* be reported as 0. Allow this case.
|
||||||
*/
|
*/
|
||||||
if (!zone_size)
|
if (!zone_sectors)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -455,24 +455,24 @@ static bool part_zone_aligned(struct gendisk *disk,
|
||||||
* use it. Check the zone size too: it should be a power of 2 number
|
* use it. Check the zone size too: it should be a power of 2 number
|
||||||
* of sectors.
|
* of sectors.
|
||||||
*/
|
*/
|
||||||
if (WARN_ON_ONCE(!is_power_of_2(zone_size))) {
|
if (WARN_ON_ONCE(!is_power_of_2(zone_sectors))) {
|
||||||
u32 rem;
|
u32 rem;
|
||||||
|
|
||||||
div_u64_rem(from, zone_size, &rem);
|
div_u64_rem(from, zone_sectors, &rem);
|
||||||
if (rem)
|
if (rem)
|
||||||
return false;
|
return false;
|
||||||
if ((from + size) < get_capacity(disk)) {
|
if ((from + size) < get_capacity(disk)) {
|
||||||
div_u64_rem(size, zone_size, &rem);
|
div_u64_rem(size, zone_sectors, &rem);
|
||||||
if (rem)
|
if (rem)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (from & (zone_size - 1))
|
if (from & (zone_sectors - 1))
|
||||||
return false;
|
return false;
|
||||||
if ((from + size) < get_capacity(disk) &&
|
if ((from + size) < get_capacity(disk) &&
|
||||||
(size & (zone_size - 1)))
|
(size & (zone_sectors - 1)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,9 +132,9 @@ config HT16K33
|
||||||
tristate "Holtek Ht16K33 LED controller with keyscan"
|
tristate "Holtek Ht16K33 LED controller with keyscan"
|
||||||
depends on FB && OF && I2C && INPUT
|
depends on FB && OF && I2C && INPUT
|
||||||
select FB_SYS_FOPS
|
select FB_SYS_FOPS
|
||||||
select FB_CFB_FILLRECT
|
select FB_SYS_FILLRECT
|
||||||
select FB_CFB_COPYAREA
|
select FB_SYS_COPYAREA
|
||||||
select FB_CFB_IMAGEBLIT
|
select FB_SYS_IMAGEBLIT
|
||||||
select INPUT_MATRIXKMAP
|
select INPUT_MATRIXKMAP
|
||||||
select FB_BACKLIGHT
|
select FB_BACKLIGHT
|
||||||
help
|
help
|
||||||
|
|
|
@ -141,8 +141,6 @@ extern void device_unblock_probing(void);
|
||||||
extern struct kset *devices_kset;
|
extern struct kset *devices_kset;
|
||||||
extern void devices_kset_move_last(struct device *dev);
|
extern void devices_kset_move_last(struct device *dev);
|
||||||
|
|
||||||
extern struct device_attribute dev_attr_deferred_probe;
|
|
||||||
|
|
||||||
#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
|
#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
|
||||||
extern void module_add_driver(struct module *mod, struct device_driver *drv);
|
extern void module_add_driver(struct module *mod, struct device_driver *drv);
|
||||||
extern void module_remove_driver(struct device_driver *drv);
|
extern void module_remove_driver(struct device_driver *drv);
|
||||||
|
|
|
@ -1060,14 +1060,8 @@ static int device_add_attrs(struct device *dev)
|
||||||
goto err_remove_dev_groups;
|
goto err_remove_dev_groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = device_create_file(dev, &dev_attr_deferred_probe);
|
|
||||||
if (error)
|
|
||||||
goto err_remove_online;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_remove_online:
|
|
||||||
device_remove_file(dev, &dev_attr_online);
|
|
||||||
err_remove_dev_groups:
|
err_remove_dev_groups:
|
||||||
device_remove_groups(dev, dev->groups);
|
device_remove_groups(dev, dev->groups);
|
||||||
err_remove_type_groups:
|
err_remove_type_groups:
|
||||||
|
@ -1085,7 +1079,6 @@ static void device_remove_attrs(struct device *dev)
|
||||||
struct class *class = dev->class;
|
struct class *class = dev->class;
|
||||||
const struct device_type *type = dev->type;
|
const struct device_type *type = dev->type;
|
||||||
|
|
||||||
device_remove_file(dev, &dev_attr_deferred_probe);
|
|
||||||
device_remove_file(dev, &dev_attr_online);
|
device_remove_file(dev, &dev_attr_online);
|
||||||
device_remove_groups(dev, dev->groups);
|
device_remove_groups(dev, dev->groups);
|
||||||
|
|
||||||
|
|
|
@ -53,19 +53,6 @@ static LIST_HEAD(deferred_probe_pending_list);
|
||||||
static LIST_HEAD(deferred_probe_active_list);
|
static LIST_HEAD(deferred_probe_active_list);
|
||||||
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
|
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
|
||||||
|
|
||||||
static ssize_t deferred_probe_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
bool value;
|
|
||||||
|
|
||||||
mutex_lock(&deferred_probe_mutex);
|
|
||||||
value = !list_empty(&dev->p->deferred_probe);
|
|
||||||
mutex_unlock(&deferred_probe_mutex);
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", value);
|
|
||||||
}
|
|
||||||
DEVICE_ATTR_RO(deferred_probe);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In some cases, like suspend to RAM or hibernation, It might be reasonable
|
* In some cases, like suspend to RAM or hibernation, It might be reasonable
|
||||||
* to prohibit probing of devices as it could be unsafe.
|
* to prohibit probing of devices as it could be unsafe.
|
||||||
|
|
|
@ -1042,6 +1042,7 @@ static int __init nbd_init(void)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < nbds_max; i++) {
|
for (i = 0; i < nbds_max; i++) {
|
||||||
|
struct request_queue *q;
|
||||||
struct gendisk *disk = alloc_disk(1 << part_shift);
|
struct gendisk *disk = alloc_disk(1 << part_shift);
|
||||||
if (!disk)
|
if (!disk)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1067,12 +1068,13 @@ static int __init nbd_init(void)
|
||||||
* every gendisk to have its very own request_queue struct.
|
* every gendisk to have its very own request_queue struct.
|
||||||
* These structs are big so we dynamically allocate them.
|
* These structs are big so we dynamically allocate them.
|
||||||
*/
|
*/
|
||||||
disk->queue = blk_mq_init_queue(&nbd_dev[i].tag_set);
|
q = blk_mq_init_queue(&nbd_dev[i].tag_set);
|
||||||
if (!disk->queue) {
|
if (IS_ERR(q)) {
|
||||||
blk_mq_free_tag_set(&nbd_dev[i].tag_set);
|
blk_mq_free_tag_set(&nbd_dev[i].tag_set);
|
||||||
put_disk(disk);
|
put_disk(disk);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
disk->queue = q;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the block layer that we are not a rotational device
|
* Tell the block layer that we are not a rotational device
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct virtblk_req {
|
||||||
struct virtio_blk_outhdr out_hdr;
|
struct virtio_blk_outhdr out_hdr;
|
||||||
struct virtio_scsi_inhdr in_hdr;
|
struct virtio_scsi_inhdr in_hdr;
|
||||||
u8 status;
|
u8 status;
|
||||||
|
u8 sense[SCSI_SENSE_BUFFERSIZE];
|
||||||
struct scatterlist sg[];
|
struct scatterlist sg[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,7 +103,8 @@ static int __virtblk_add_req(struct virtqueue *vq,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
|
if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
|
||||||
sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
|
memcpy(vbr->sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
|
||||||
|
sg_init_one(&sense, vbr->sense, SCSI_SENSE_BUFFERSIZE);
|
||||||
sgs[num_out + num_in++] = &sense;
|
sgs[num_out + num_in++] = &sense;
|
||||||
sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
|
sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
|
||||||
sgs[num_out + num_in++] = &inhdr;
|
sgs[num_out + num_in++] = &inhdr;
|
||||||
|
@ -628,11 +630,12 @@ static int virtblk_probe(struct virtio_device *vdev)
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put_disk;
|
goto out_put_disk;
|
||||||
|
|
||||||
q = vblk->disk->queue = blk_mq_init_queue(&vblk->tag_set);
|
q = blk_mq_init_queue(&vblk->tag_set);
|
||||||
if (IS_ERR(q)) {
|
if (IS_ERR(q)) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_free_tags;
|
goto out_free_tags;
|
||||||
}
|
}
|
||||||
|
vblk->disk->queue = q;
|
||||||
|
|
||||||
q->queuedata = vblk;
|
q->queuedata = vblk;
|
||||||
|
|
||||||
|
|
|
@ -381,9 +381,6 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
|
||||||
char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
|
char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!pfn_valid(PFN_DOWN(p)))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
read = 0;
|
read = 0;
|
||||||
if (p < (unsigned long) high_memory) {
|
if (p < (unsigned long) high_memory) {
|
||||||
low_count = count;
|
low_count = count;
|
||||||
|
@ -412,6 +409,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
|
||||||
* by the kernel or data corruption may occur
|
* by the kernel or data corruption may occur
|
||||||
*/
|
*/
|
||||||
kbuf = xlate_dev_kmem_ptr((void *)p);
|
kbuf = xlate_dev_kmem_ptr((void *)p);
|
||||||
|
if (!virt_addr_valid(kbuf))
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
if (copy_to_user(buf, kbuf, sz))
|
if (copy_to_user(buf, kbuf, sz))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -482,6 +481,8 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
|
||||||
* corruption may occur.
|
* corruption may occur.
|
||||||
*/
|
*/
|
||||||
ptr = xlate_dev_kmem_ptr((void *)p);
|
ptr = xlate_dev_kmem_ptr((void *)p);
|
||||||
|
if (!virt_addr_valid(ptr))
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
copied = copy_from_user(ptr, buf, sz);
|
copied = copy_from_user(ptr, buf, sz);
|
||||||
if (copied) {
|
if (copied) {
|
||||||
|
@ -512,9 +513,6 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
|
||||||
char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
|
char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!pfn_valid(PFN_DOWN(p)))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
if (p < (unsigned long) high_memory) {
|
if (p < (unsigned long) high_memory) {
|
||||||
unsigned long to_write = min_t(unsigned long, count,
|
unsigned long to_write = min_t(unsigned long, count,
|
||||||
(unsigned long)high_memory - p);
|
(unsigned long)high_memory - p);
|
||||||
|
|
|
@ -290,6 +290,7 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||||
struct pardevice *pdev = NULL;
|
struct pardevice *pdev = NULL;
|
||||||
char *name;
|
char *name;
|
||||||
struct pardev_cb ppdev_cb;
|
struct pardev_cb ppdev_cb;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
|
name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
|
@ -298,8 +299,8 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||||
port = parport_find_number(minor);
|
port = parport_find_number(minor);
|
||||||
if (!port) {
|
if (!port) {
|
||||||
pr_warn("%s: no associated port!\n", name);
|
pr_warn("%s: no associated port!\n", name);
|
||||||
kfree(name);
|
rc = -ENXIO;
|
||||||
return -ENXIO;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ppdev_cb, 0, sizeof(ppdev_cb));
|
memset(&ppdev_cb, 0, sizeof(ppdev_cb));
|
||||||
|
@ -308,16 +309,18 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||||
ppdev_cb.private = pp;
|
ppdev_cb.private = pp;
|
||||||
pdev = parport_register_dev_model(port, name, &ppdev_cb, minor);
|
pdev = parport_register_dev_model(port, name, &ppdev_cb, minor);
|
||||||
parport_put_port(port);
|
parport_put_port(port);
|
||||||
kfree(name);
|
|
||||||
|
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
pr_warn("%s: failed to register device!\n", name);
|
pr_warn("%s: failed to register device!\n", name);
|
||||||
return -ENXIO;
|
rc = -ENXIO;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pp->pdev = pdev;
|
pp->pdev = pdev;
|
||||||
dev_dbg(&pdev->dev, "registered pardevice\n");
|
dev_dbg(&pdev->dev, "registered pardevice\n");
|
||||||
return 0;
|
err:
|
||||||
|
kfree(name);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ieee1284_phase init_phase(int mode)
|
static enum ieee1284_phase init_phase(int mode)
|
||||||
|
|
|
@ -24,5 +24,5 @@ config DW_DMAC_PCI
|
||||||
select DW_DMAC_CORE
|
select DW_DMAC_CORE
|
||||||
help
|
help
|
||||||
Support the Synopsys DesignWare AHB DMA controller on the
|
Support the Synopsys DesignWare AHB DMA controller on the
|
||||||
platfroms that enumerate it as a PCI device. For example,
|
platforms that enumerate it as a PCI device. For example,
|
||||||
Intel Medfield has integrated this GPDMA controller.
|
Intel Medfield has integrated this GPDMA controller.
|
||||||
|
|
|
@ -64,6 +64,8 @@
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
|
#define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
|
#define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
|
||||||
|
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IOAT_SKX 0x2021
|
||||||
|
|
||||||
#define IOAT_VER_1_2 0x12 /* Version 1.2 */
|
#define IOAT_VER_1_2 0x12 /* Version 1.2 */
|
||||||
#define IOAT_VER_2_0 0x20 /* Version 2.0 */
|
#define IOAT_VER_2_0 0x20 /* Version 2.0 */
|
||||||
#define IOAT_VER_3_0 0x30 /* Version 3.0 */
|
#define IOAT_VER_3_0 0x30 /* Version 3.0 */
|
||||||
|
|
|
@ -106,6 +106,8 @@ static struct pci_device_id ioat_pci_tbl[] = {
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) },
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) },
|
||||||
|
|
||||||
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SKX) },
|
||||||
|
|
||||||
/* I/OAT v3.3 platforms */
|
/* I/OAT v3.3 platforms */
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) },
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) },
|
||||||
|
@ -243,10 +245,15 @@ static bool is_bdx_ioat(struct pci_dev *pdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_skx_ioat(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
return (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_SKX) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_xeon_cb32(struct pci_dev *pdev)
|
static bool is_xeon_cb32(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) ||
|
return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) ||
|
||||||
is_hsw_ioat(pdev) || is_bdx_ioat(pdev);
|
is_hsw_ioat(pdev) || is_bdx_ioat(pdev) || is_skx_ioat(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_bwd_ioat(struct pci_dev *pdev)
|
bool is_bwd_ioat(struct pci_dev *pdev)
|
||||||
|
@ -693,7 +700,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c)
|
||||||
/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
|
/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
|
||||||
ioat_chan->completion =
|
ioat_chan->completion =
|
||||||
dma_pool_zalloc(ioat_chan->ioat_dma->completion_pool,
|
dma_pool_zalloc(ioat_chan->ioat_dma->completion_pool,
|
||||||
GFP_KERNEL, &ioat_chan->completion_dma);
|
GFP_NOWAIT, &ioat_chan->completion_dma);
|
||||||
if (!ioat_chan->completion)
|
if (!ioat_chan->completion)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -703,7 +710,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c)
|
||||||
ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
|
ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
|
||||||
|
|
||||||
order = IOAT_MAX_ORDER;
|
order = IOAT_MAX_ORDER;
|
||||||
ring = ioat_alloc_ring(c, order, GFP_KERNEL);
|
ring = ioat_alloc_ring(c, order, GFP_NOWAIT);
|
||||||
if (!ring)
|
if (!ring)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -1357,6 +1364,8 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
|
|
||||||
device->version = readb(device->reg_base + IOAT_VER_OFFSET);
|
device->version = readb(device->reg_base + IOAT_VER_OFFSET);
|
||||||
if (device->version >= IOAT_VER_3_0) {
|
if (device->version >= IOAT_VER_3_0) {
|
||||||
|
if (is_skx_ioat(pdev))
|
||||||
|
device->version = IOAT_VER_3_2;
|
||||||
err = ioat3_dma_probe(device, ioat_dca_enabled);
|
err = ioat3_dma_probe(device, ioat_dca_enabled);
|
||||||
|
|
||||||
if (device->version >= IOAT_VER_3_3)
|
if (device->version >= IOAT_VER_3_3)
|
||||||
|
|
|
@ -938,6 +938,23 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
|
||||||
d->ccr |= CCR_DST_AMODE_POSTINC;
|
d->ccr |= CCR_DST_AMODE_POSTINC;
|
||||||
if (port_window) {
|
if (port_window) {
|
||||||
d->ccr |= CCR_SRC_AMODE_DBLIDX;
|
d->ccr |= CCR_SRC_AMODE_DBLIDX;
|
||||||
|
|
||||||
|
if (port_window_bytes >= 64)
|
||||||
|
d->csdp |= CSDP_SRC_BURST_64;
|
||||||
|
else if (port_window_bytes >= 32)
|
||||||
|
d->csdp |= CSDP_SRC_BURST_32;
|
||||||
|
else if (port_window_bytes >= 16)
|
||||||
|
d->csdp |= CSDP_SRC_BURST_16;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
d->ccr |= CCR_SRC_AMODE_CONSTANT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
|
||||||
|
|
||||||
|
d->ccr |= CCR_SRC_AMODE_POSTINC;
|
||||||
|
if (port_window) {
|
||||||
|
d->ccr |= CCR_DST_AMODE_DBLIDX;
|
||||||
d->ei = 1;
|
d->ei = 1;
|
||||||
/*
|
/*
|
||||||
* One frame covers the port_window and by configure
|
* One frame covers the port_window and by configure
|
||||||
|
@ -948,27 +965,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
|
||||||
d->fi = -(port_window_bytes - 1);
|
d->fi = -(port_window_bytes - 1);
|
||||||
|
|
||||||
if (port_window_bytes >= 64)
|
if (port_window_bytes >= 64)
|
||||||
d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
|
d->csdp |= CSDP_DST_BURST_64;
|
||||||
else if (port_window_bytes >= 32)
|
else if (port_window_bytes >= 32)
|
||||||
d->csdp = CSDP_SRC_BURST_32 | CSDP_SRC_PACKED;
|
d->csdp |= CSDP_DST_BURST_32;
|
||||||
else if (port_window_bytes >= 16)
|
else if (port_window_bytes >= 16)
|
||||||
d->csdp = CSDP_SRC_BURST_16 | CSDP_SRC_PACKED;
|
d->csdp |= CSDP_DST_BURST_16;
|
||||||
} else {
|
|
||||||
d->ccr |= CCR_SRC_AMODE_CONSTANT;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
|
|
||||||
|
|
||||||
d->ccr |= CCR_SRC_AMODE_POSTINC;
|
|
||||||
if (port_window) {
|
|
||||||
d->ccr |= CCR_DST_AMODE_DBLIDX;
|
|
||||||
|
|
||||||
if (port_window_bytes >= 64)
|
|
||||||
d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
|
|
||||||
else if (port_window_bytes >= 32)
|
|
||||||
d->csdp = CSDP_DST_BURST_32 | CSDP_DST_PACKED;
|
|
||||||
else if (port_window_bytes >= 16)
|
|
||||||
d->csdp = CSDP_DST_BURST_16 | CSDP_DST_PACKED;
|
|
||||||
} else {
|
} else {
|
||||||
d->ccr |= CCR_DST_AMODE_CONSTANT;
|
d->ccr |= CCR_DST_AMODE_CONSTANT;
|
||||||
}
|
}
|
||||||
|
@ -1017,7 +1018,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
|
||||||
osg->addr = sg_dma_address(sgent);
|
osg->addr = sg_dma_address(sgent);
|
||||||
osg->en = en;
|
osg->en = en;
|
||||||
osg->fn = sg_dma_len(sgent) / frame_bytes;
|
osg->fn = sg_dma_len(sgent) / frame_bytes;
|
||||||
if (port_window && dir == DMA_MEM_TO_DEV) {
|
if (port_window && dir == DMA_DEV_TO_MEM) {
|
||||||
osg->ei = 1;
|
osg->ei = 1;
|
||||||
/*
|
/*
|
||||||
* One frame covers the port_window and by configure
|
* One frame covers the port_window and by configure
|
||||||
|
@ -1452,6 +1453,7 @@ static int omap_dma_probe(struct platform_device *pdev)
|
||||||
struct omap_dmadev *od;
|
struct omap_dmadev *od;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int rc, i, irq;
|
int rc, i, irq;
|
||||||
|
u32 lch_count;
|
||||||
|
|
||||||
od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
|
od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
|
||||||
if (!od)
|
if (!od)
|
||||||
|
@ -1494,20 +1496,31 @@ static int omap_dma_probe(struct platform_device *pdev)
|
||||||
spin_lock_init(&od->lock);
|
spin_lock_init(&od->lock);
|
||||||
spin_lock_init(&od->irq_lock);
|
spin_lock_init(&od->irq_lock);
|
||||||
|
|
||||||
if (!pdev->dev.of_node) {
|
/* Number of DMA requests */
|
||||||
od->dma_requests = od->plat->dma_attr->lch_count;
|
od->dma_requests = OMAP_SDMA_REQUESTS;
|
||||||
if (unlikely(!od->dma_requests))
|
if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node,
|
||||||
od->dma_requests = OMAP_SDMA_REQUESTS;
|
"dma-requests",
|
||||||
} else if (of_property_read_u32(pdev->dev.of_node, "dma-requests",
|
&od->dma_requests)) {
|
||||||
&od->dma_requests)) {
|
|
||||||
dev_info(&pdev->dev,
|
dev_info(&pdev->dev,
|
||||||
"Missing dma-requests property, using %u.\n",
|
"Missing dma-requests property, using %u.\n",
|
||||||
OMAP_SDMA_REQUESTS);
|
OMAP_SDMA_REQUESTS);
|
||||||
od->dma_requests = OMAP_SDMA_REQUESTS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
od->lch_map = devm_kcalloc(&pdev->dev, od->dma_requests,
|
/* Number of available logical channels */
|
||||||
sizeof(*od->lch_map), GFP_KERNEL);
|
if (!pdev->dev.of_node) {
|
||||||
|
lch_count = od->plat->dma_attr->lch_count;
|
||||||
|
if (unlikely(!lch_count))
|
||||||
|
lch_count = OMAP_SDMA_CHANNELS;
|
||||||
|
} else if (of_property_read_u32(pdev->dev.of_node, "dma-channels",
|
||||||
|
&lch_count)) {
|
||||||
|
dev_info(&pdev->dev,
|
||||||
|
"Missing dma-channels property, using %u.\n",
|
||||||
|
OMAP_SDMA_CHANNELS);
|
||||||
|
lch_count = OMAP_SDMA_CHANNELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
od->lch_map = devm_kcalloc(&pdev->dev, lch_count, sizeof(*od->lch_map),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!od->lch_map)
|
if (!od->lch_map)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -448,6 +448,9 @@ struct dma_pl330_chan {
|
||||||
|
|
||||||
/* for cyclic capability */
|
/* for cyclic capability */
|
||||||
bool cyclic;
|
bool cyclic;
|
||||||
|
|
||||||
|
/* for runtime pm tracking */
|
||||||
|
bool active;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pl330_dmac {
|
struct pl330_dmac {
|
||||||
|
@ -2033,6 +2036,7 @@ static void pl330_tasklet(unsigned long data)
|
||||||
_stop(pch->thread);
|
_stop(pch->thread);
|
||||||
spin_unlock(&pch->thread->dmac->lock);
|
spin_unlock(&pch->thread->dmac->lock);
|
||||||
power_down = true;
|
power_down = true;
|
||||||
|
pch->active = false;
|
||||||
} else {
|
} else {
|
||||||
/* Make sure the PL330 Channel thread is active */
|
/* Make sure the PL330 Channel thread is active */
|
||||||
spin_lock(&pch->thread->dmac->lock);
|
spin_lock(&pch->thread->dmac->lock);
|
||||||
|
@ -2052,6 +2056,7 @@ static void pl330_tasklet(unsigned long data)
|
||||||
desc->status = PREP;
|
desc->status = PREP;
|
||||||
list_move_tail(&desc->node, &pch->work_list);
|
list_move_tail(&desc->node, &pch->work_list);
|
||||||
if (power_down) {
|
if (power_down) {
|
||||||
|
pch->active = true;
|
||||||
spin_lock(&pch->thread->dmac->lock);
|
spin_lock(&pch->thread->dmac->lock);
|
||||||
_start(pch->thread);
|
_start(pch->thread);
|
||||||
spin_unlock(&pch->thread->dmac->lock);
|
spin_unlock(&pch->thread->dmac->lock);
|
||||||
|
@ -2166,6 +2171,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct pl330_dmac *pl330 = pch->dmac;
|
struct pl330_dmac *pl330 = pch->dmac;
|
||||||
LIST_HEAD(list);
|
LIST_HEAD(list);
|
||||||
|
bool power_down = false;
|
||||||
|
|
||||||
pm_runtime_get_sync(pl330->ddma.dev);
|
pm_runtime_get_sync(pl330->ddma.dev);
|
||||||
spin_lock_irqsave(&pch->lock, flags);
|
spin_lock_irqsave(&pch->lock, flags);
|
||||||
|
@ -2176,6 +2182,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||||
pch->thread->req[0].desc = NULL;
|
pch->thread->req[0].desc = NULL;
|
||||||
pch->thread->req[1].desc = NULL;
|
pch->thread->req[1].desc = NULL;
|
||||||
pch->thread->req_running = -1;
|
pch->thread->req_running = -1;
|
||||||
|
power_down = pch->active;
|
||||||
|
pch->active = false;
|
||||||
|
|
||||||
/* Mark all desc done */
|
/* Mark all desc done */
|
||||||
list_for_each_entry(desc, &pch->submitted_list, node) {
|
list_for_each_entry(desc, &pch->submitted_list, node) {
|
||||||
|
@ -2193,6 +2201,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||||
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
||||||
spin_unlock_irqrestore(&pch->lock, flags);
|
spin_unlock_irqrestore(&pch->lock, flags);
|
||||||
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
||||||
|
if (power_down)
|
||||||
|
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
||||||
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2357,6 +2367,7 @@ static void pl330_issue_pending(struct dma_chan *chan)
|
||||||
* updated on work_list emptiness status.
|
* updated on work_list emptiness status.
|
||||||
*/
|
*/
|
||||||
WARN_ON(list_empty(&pch->submitted_list));
|
WARN_ON(list_empty(&pch->submitted_list));
|
||||||
|
pch->active = true;
|
||||||
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
||||||
}
|
}
|
||||||
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
|
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
|
||||||
|
|
|
@ -986,6 +986,7 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
|
||||||
{
|
{
|
||||||
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
|
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
|
||||||
struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
|
struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
|
||||||
|
struct rcar_dmac_chan_map *map = &rchan->map;
|
||||||
struct rcar_dmac_desc_page *page, *_page;
|
struct rcar_dmac_desc_page *page, *_page;
|
||||||
struct rcar_dmac_desc *desc;
|
struct rcar_dmac_desc *desc;
|
||||||
LIST_HEAD(list);
|
LIST_HEAD(list);
|
||||||
|
@ -1019,6 +1020,13 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
|
||||||
free_page((unsigned long)page);
|
free_page((unsigned long)page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove slave mapping if present. */
|
||||||
|
if (map->slave.xfer_size) {
|
||||||
|
dma_unmap_resource(chan->device->dev, map->addr,
|
||||||
|
map->slave.xfer_size, map->dir, 0);
|
||||||
|
map->slave.xfer_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
pm_runtime_put(chan->device->dev);
|
pm_runtime_put(chan->device->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -880,7 +880,7 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
|
||||||
struct virt_dma_desc *vdesc;
|
struct virt_dma_desc *vdesc;
|
||||||
enum dma_status status;
|
enum dma_status status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 residue;
|
u32 residue = 0;
|
||||||
|
|
||||||
status = dma_cookie_status(c, cookie, state);
|
status = dma_cookie_status(c, cookie, state);
|
||||||
if ((status == DMA_COMPLETE) || (!state))
|
if ((status == DMA_COMPLETE) || (!state))
|
||||||
|
@ -888,16 +888,12 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
|
||||||
|
|
||||||
spin_lock_irqsave(&chan->vchan.lock, flags);
|
spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||||
vdesc = vchan_find_desc(&chan->vchan, cookie);
|
vdesc = vchan_find_desc(&chan->vchan, cookie);
|
||||||
if (cookie == chan->desc->vdesc.tx.cookie) {
|
if (chan->desc && cookie == chan->desc->vdesc.tx.cookie)
|
||||||
residue = stm32_dma_desc_residue(chan, chan->desc,
|
residue = stm32_dma_desc_residue(chan, chan->desc,
|
||||||
chan->next_sg);
|
chan->next_sg);
|
||||||
} else if (vdesc) {
|
else if (vdesc)
|
||||||
residue = stm32_dma_desc_residue(chan,
|
residue = stm32_dma_desc_residue(chan,
|
||||||
to_stm32_dma_desc(vdesc), 0);
|
to_stm32_dma_desc(vdesc), 0);
|
||||||
} else {
|
|
||||||
residue = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dma_set_residue(state, residue);
|
dma_set_residue(state, residue);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
||||||
|
@ -972,21 +968,18 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||||
struct stm32_dma_chan *chan;
|
struct stm32_dma_chan *chan;
|
||||||
struct dma_chan *c;
|
struct dma_chan *c;
|
||||||
|
|
||||||
if (dma_spec->args_count < 3)
|
if (dma_spec->args_count < 4)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cfg.channel_id = dma_spec->args[0];
|
cfg.channel_id = dma_spec->args[0];
|
||||||
cfg.request_line = dma_spec->args[1];
|
cfg.request_line = dma_spec->args[1];
|
||||||
cfg.stream_config = dma_spec->args[2];
|
cfg.stream_config = dma_spec->args[2];
|
||||||
cfg.threshold = 0;
|
cfg.threshold = dma_spec->args[3];
|
||||||
|
|
||||||
if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
|
if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
|
||||||
STM32_DMA_MAX_REQUEST_ID))
|
STM32_DMA_MAX_REQUEST_ID))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (dma_spec->args_count > 3)
|
|
||||||
cfg.threshold = dma_spec->args[3];
|
|
||||||
|
|
||||||
chan = &dmadev->chan[cfg.channel_id];
|
chan = &dmadev->chan[cfg.channel_id];
|
||||||
|
|
||||||
c = dma_get_slave_channel(&chan->vchan.chan);
|
c = dma_get_slave_channel(&chan->vchan.chan);
|
||||||
|
|
|
@ -149,6 +149,7 @@ static int ti_am335x_xbar_probe(struct platform_device *pdev)
|
||||||
match = of_match_node(ti_am335x_master_match, dma_node);
|
match = of_match_node(ti_am335x_master_match, dma_node);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
dev_err(&pdev->dev, "DMA master is not supported\n");
|
dev_err(&pdev->dev, "DMA master is not supported\n");
|
||||||
|
of_node_put(dma_node);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,6 +340,7 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
|
||||||
match = of_match_node(ti_dra7_master_match, dma_node);
|
match = of_match_node(ti_dra7_master_match, dma_node);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
dev_err(&pdev->dev, "DMA master is not supported\n");
|
dev_err(&pdev->dev, "DMA master is not supported\n");
|
||||||
|
of_node_put(dma_node);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -453,7 +453,7 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id)
|
||||||
dev_err(&edev->dev, "out of memory in extcon_set_state\n");
|
dev_err(&edev->dev, "out of memory in extcon_set_state\n");
|
||||||
kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
|
kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
|
||||||
|
|
||||||
return 0;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = name_show(&edev->dev, NULL, prop_buf);
|
length = name_show(&edev->dev, NULL, prop_buf);
|
||||||
|
|
|
@ -71,8 +71,7 @@ void __init efi_fake_memmap(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate memory for new EFI memmap */
|
/* allocate memory for new EFI memmap */
|
||||||
new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map,
|
new_memmap_phy = efi_memmap_alloc(new_nr_map);
|
||||||
PAGE_SIZE);
|
|
||||||
if (!new_memmap_phy)
|
if (!new_memmap_phy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -39,14 +39,6 @@ efi_status_t efi_file_close(void *handle);
|
||||||
|
|
||||||
unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
|
unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
|
||||||
|
|
||||||
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
|
||||||
unsigned long orig_fdt_size,
|
|
||||||
void *fdt, int new_fdt_size, char *cmdline_ptr,
|
|
||||||
u64 initrd_addr, u64 initrd_size,
|
|
||||||
efi_memory_desc_t *memory_map,
|
|
||||||
unsigned long map_size, unsigned long desc_size,
|
|
||||||
u32 desc_ver);
|
|
||||||
|
|
||||||
efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
void *handle,
|
void *handle,
|
||||||
unsigned long *new_fdt_addr,
|
unsigned long *new_fdt_addr,
|
||||||
|
|
|
@ -16,13 +16,10 @@
|
||||||
|
|
||||||
#include "efistub.h"
|
#include "efistub.h"
|
||||||
|
|
||||||
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
||||||
unsigned long orig_fdt_size,
|
unsigned long orig_fdt_size,
|
||||||
void *fdt, int new_fdt_size, char *cmdline_ptr,
|
void *fdt, int new_fdt_size, char *cmdline_ptr,
|
||||||
u64 initrd_addr, u64 initrd_size,
|
u64 initrd_addr, u64 initrd_size)
|
||||||
efi_memory_desc_t *memory_map,
|
|
||||||
unsigned long map_size, unsigned long desc_size,
|
|
||||||
u32 desc_ver)
|
|
||||||
{
|
{
|
||||||
int node, num_rsv;
|
int node, num_rsv;
|
||||||
int status;
|
int status;
|
||||||
|
@ -101,25 +98,23 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
|
fdt_val64 = U64_MAX; /* placeholder */
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
|
||||||
&fdt_val64, sizeof(fdt_val64));
|
&fdt_val64, sizeof(fdt_val64));
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val32 = cpu_to_fdt32(map_size);
|
fdt_val32 = U32_MAX; /* placeholder */
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
|
||||||
&fdt_val32, sizeof(fdt_val32));
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val32 = cpu_to_fdt32(desc_size);
|
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
|
||||||
&fdt_val32, sizeof(fdt_val32));
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val32 = cpu_to_fdt32(desc_ver);
|
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
|
||||||
&fdt_val32, sizeof(fdt_val32));
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -148,6 +143,43 @@ fdt_set_fail:
|
||||||
return EFI_LOAD_ERROR;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
|
||||||
|
{
|
||||||
|
int node = fdt_path_offset(fdt, "/chosen");
|
||||||
|
u64 fdt_val64;
|
||||||
|
u32 fdt_val32;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (node < 0)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start",
|
||||||
|
&fdt_val64, sizeof(fdt_val64));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val32 = cpu_to_fdt32(*map->map_size);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size",
|
||||||
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val32 = cpu_to_fdt32(*map->desc_size);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size",
|
||||||
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val32 = cpu_to_fdt32(*map->desc_ver);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver",
|
||||||
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef EFI_FDT_ALIGN
|
#ifndef EFI_FDT_ALIGN
|
||||||
#define EFI_FDT_ALIGN EFI_PAGE_SIZE
|
#define EFI_FDT_ALIGN EFI_PAGE_SIZE
|
||||||
#endif
|
#endif
|
||||||
|
@ -243,20 +275,10 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Now that we have done our final memory allocation (and free)
|
|
||||||
* we can get the memory map key needed for
|
|
||||||
* exit_boot_services().
|
|
||||||
*/
|
|
||||||
status = efi_get_memory_map(sys_table, &map);
|
|
||||||
if (status != EFI_SUCCESS)
|
|
||||||
goto fail_free_new_fdt;
|
|
||||||
|
|
||||||
status = update_fdt(sys_table,
|
status = update_fdt(sys_table,
|
||||||
(void *)fdt_addr, fdt_size,
|
(void *)fdt_addr, fdt_size,
|
||||||
(void *)*new_fdt_addr, new_fdt_size,
|
(void *)*new_fdt_addr, new_fdt_size,
|
||||||
cmdline_ptr, initrd_addr, initrd_size,
|
cmdline_ptr, initrd_addr, initrd_size);
|
||||||
memory_map, map_size, desc_size, desc_ver);
|
|
||||||
|
|
||||||
/* Succeeding the first time is the expected case. */
|
/* Succeeding the first time is the expected case. */
|
||||||
if (status == EFI_SUCCESS)
|
if (status == EFI_SUCCESS)
|
||||||
|
@ -266,20 +288,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
/*
|
/*
|
||||||
* We need to allocate more space for the new
|
* We need to allocate more space for the new
|
||||||
* device tree, so free existing buffer that is
|
* device tree, so free existing buffer that is
|
||||||
* too small. Also free memory map, as we will need
|
* too small.
|
||||||
* to get new one that reflects the free/alloc we do
|
|
||||||
* on the device tree buffer.
|
|
||||||
*/
|
*/
|
||||||
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
||||||
sys_table->boottime->free_pool(memory_map);
|
|
||||||
new_fdt_size += EFI_PAGE_SIZE;
|
new_fdt_size += EFI_PAGE_SIZE;
|
||||||
} else {
|
} else {
|
||||||
pr_efi_err(sys_table, "Unable to construct new device tree.\n");
|
pr_efi_err(sys_table, "Unable to construct new device tree.\n");
|
||||||
goto fail_free_mmap;
|
goto fail_free_new_fdt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_table->boottime->free_pool(memory_map);
|
|
||||||
priv.runtime_map = runtime_map;
|
priv.runtime_map = runtime_map;
|
||||||
priv.runtime_entry_count = &runtime_entry_count;
|
priv.runtime_entry_count = &runtime_entry_count;
|
||||||
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
||||||
|
@ -288,6 +306,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
if (status == EFI_SUCCESS) {
|
if (status == EFI_SUCCESS) {
|
||||||
efi_set_virtual_address_map_t *svam;
|
efi_set_virtual_address_map_t *svam;
|
||||||
|
|
||||||
|
status = update_fdt_memmap((void *)*new_fdt_addr, &map);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
/*
|
||||||
|
* The kernel won't get far without the memory map, but
|
||||||
|
* may still be able to print something meaningful so
|
||||||
|
* return success here.
|
||||||
|
*/
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Install the new virtual address map */
|
/* Install the new virtual address map */
|
||||||
svam = sys_table->runtime->set_virtual_address_map;
|
svam = sys_table->runtime->set_virtual_address_map;
|
||||||
status = svam(runtime_entry_count * desc_size, desc_size,
|
status = svam(runtime_entry_count * desc_size, desc_size,
|
||||||
|
@ -319,9 +347,6 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
|
|
||||||
pr_efi_err(sys_table, "Exit boot services failed.\n");
|
pr_efi_err(sys_table, "Exit boot services failed.\n");
|
||||||
|
|
||||||
fail_free_mmap:
|
|
||||||
sys_table->boottime->free_pool(memory_map);
|
|
||||||
|
|
||||||
fail_free_new_fdt:
|
fail_free_new_fdt:
|
||||||
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,44 @@
|
||||||
#include <linux/efi.h>
|
#include <linux/efi.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <asm/early_ioremap.h>
|
#include <asm/early_ioremap.h>
|
||||||
|
#include <linux/memblock.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
|
||||||
|
{
|
||||||
|
return memblock_alloc(size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned int order = get_order(size);
|
||||||
|
struct page *p = alloc_pages(GFP_KERNEL, order);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return PFN_PHYS(page_to_pfn(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_memmap_alloc - Allocate memory for the EFI memory map
|
||||||
|
* @num_entries: Number of entries in the allocated map.
|
||||||
|
*
|
||||||
|
* Depending on whether mm_init() has already been invoked or not,
|
||||||
|
* either memblock or "normal" page allocation is used.
|
||||||
|
*
|
||||||
|
* Returns the physical address of the allocated memory map on
|
||||||
|
* success, zero on failure.
|
||||||
|
*/
|
||||||
|
phys_addr_t __init efi_memmap_alloc(unsigned int num_entries)
|
||||||
|
{
|
||||||
|
unsigned long size = num_entries * efi.memmap.desc_size;
|
||||||
|
|
||||||
|
if (slab_is_available())
|
||||||
|
return __efi_memmap_alloc_late(size);
|
||||||
|
|
||||||
|
return __efi_memmap_alloc_early(size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __efi_memmap_init - Common code for mapping the EFI memory map
|
* __efi_memmap_init - Common code for mapping the EFI memory map
|
||||||
|
|
|
@ -2496,6 +2496,7 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
|
||||||
#if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
|
#if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
|
||||||
|
|
|
@ -39,6 +39,9 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
|
if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
|
||||||
return rdesc;
|
return rdesc;
|
||||||
|
|
||||||
|
if (*rsize < 4)
|
||||||
|
return rdesc;
|
||||||
|
|
||||||
for (i = 0; i < *rsize - 4; i++)
|
for (i = 0; i < *rsize - 4; i++)
|
||||||
if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
|
if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
|
||||||
rdesc[i] = 0x19;
|
rdesc[i] = 0x19;
|
||||||
|
|
|
@ -816,6 +816,9 @@
|
||||||
#define USB_VENDOR_ID_PETALYNX 0x18b1
|
#define USB_VENDOR_ID_PETALYNX 0x18b1
|
||||||
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
|
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
|
||||||
|
|
||||||
|
#define USB_VENDOR_ID_PETZL 0x2122
|
||||||
|
#define USB_DEVICE_ID_PETZL_HEADLAMP 0x1234
|
||||||
|
|
||||||
#define USB_VENDOR_ID_PHILIPS 0x0471
|
#define USB_VENDOR_ID_PHILIPS 0x0471
|
||||||
#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
|
#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
|
||||||
|
|
||||||
|
|
|
@ -426,6 +426,15 @@ static int i2c_hid_hwreset(struct i2c_client *client)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The HID over I2C specification states that if a DEVICE needs time
|
||||||
|
* after the PWR_ON request, it should utilise CLOCK stretching.
|
||||||
|
* However, it has been observered that the Windows driver provides a
|
||||||
|
* 1ms sleep between the PWR_ON and RESET requests and that some devices
|
||||||
|
* rely on this.
|
||||||
|
*/
|
||||||
|
usleep_range(1000, 5000);
|
||||||
|
|
||||||
i2c_hid_dbg(ihid, "resetting...\n");
|
i2c_hid_dbg(ihid, "resetting...\n");
|
||||||
|
|
||||||
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
|
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
|
||||||
|
|
|
@ -585,10 +585,29 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
||||||
u8 command, int size, union i2c_smbus_data *data)
|
u8 command, int size, union i2c_smbus_data *data)
|
||||||
{
|
{
|
||||||
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
|
struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
|
||||||
|
unsigned short piix4_smba = adapdata->smba;
|
||||||
|
int retries = MAX_TIMEOUT;
|
||||||
|
int smbslvcnt;
|
||||||
u8 smba_en_lo;
|
u8 smba_en_lo;
|
||||||
u8 port;
|
u8 port;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
/* Request the SMBUS semaphore, avoid conflicts with the IMC */
|
||||||
|
smbslvcnt = inb_p(SMBSLVCNT);
|
||||||
|
do {
|
||||||
|
outb_p(smbslvcnt | 0x10, SMBSLVCNT);
|
||||||
|
|
||||||
|
/* Check the semaphore status */
|
||||||
|
smbslvcnt = inb_p(SMBSLVCNT);
|
||||||
|
if (smbslvcnt & 0x10)
|
||||||
|
break;
|
||||||
|
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
} while (--retries);
|
||||||
|
/* SMBus is still owned by the IMC, we give up */
|
||||||
|
if (!retries)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
mutex_lock(&piix4_mutex_sb800);
|
mutex_lock(&piix4_mutex_sb800);
|
||||||
|
|
||||||
outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
|
outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
|
||||||
|
@ -606,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
||||||
|
|
||||||
mutex_unlock(&piix4_mutex_sb800);
|
mutex_unlock(&piix4_mutex_sb800);
|
||||||
|
|
||||||
|
/* Release the semaphore */
|
||||||
|
outb_p(smbslvcnt | 0x20, SMBSLVCNT);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -931,7 +931,10 @@ static int i2c_device_probe(struct device *dev)
|
||||||
if (!client->irq) {
|
if (!client->irq) {
|
||||||
int irq = -ENOENT;
|
int irq = -ENOENT;
|
||||||
|
|
||||||
if (dev->of_node) {
|
if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
|
||||||
|
dev_dbg(dev, "Using Host Notify IRQ\n");
|
||||||
|
irq = i2c_smbus_host_notify_to_irq(client);
|
||||||
|
} else if (dev->of_node) {
|
||||||
irq = of_irq_get_byname(dev->of_node, "irq");
|
irq = of_irq_get_byname(dev->of_node, "irq");
|
||||||
if (irq == -EINVAL || irq == -ENODATA)
|
if (irq == -EINVAL || irq == -ENODATA)
|
||||||
irq = of_irq_get(dev->of_node, 0);
|
irq = of_irq_get(dev->of_node, 0);
|
||||||
|
@ -940,14 +943,7 @@ static int i2c_device_probe(struct device *dev)
|
||||||
}
|
}
|
||||||
if (irq == -EPROBE_DEFER)
|
if (irq == -EPROBE_DEFER)
|
||||||
return irq;
|
return irq;
|
||||||
/*
|
|
||||||
* ACPI and OF did not find any useful IRQ, try to see
|
|
||||||
* if Host Notify can be used.
|
|
||||||
*/
|
|
||||||
if (irq < 0) {
|
|
||||||
dev_dbg(dev, "Using Host Notify IRQ\n");
|
|
||||||
irq = i2c_smbus_host_notify_to_irq(client);
|
|
||||||
}
|
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
irq = 0;
|
irq = 0;
|
||||||
|
|
||||||
|
@ -1708,7 +1704,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
|
||||||
|
|
||||||
if (i2c_check_addr_validity(addr, info.flags)) {
|
if (i2c_check_addr_validity(addr, info.flags)) {
|
||||||
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
|
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
|
||||||
info.addr, node->full_name);
|
addr, node->full_name);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1716,6 +1712,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
|
||||||
info.of_node = of_node_get(node);
|
info.of_node = of_node_get(node);
|
||||||
info.archdata = &dev_ad;
|
info.archdata = &dev_ad;
|
||||||
|
|
||||||
|
if (of_property_read_bool(node, "host-notify"))
|
||||||
|
info.flags |= I2C_CLIENT_HOST_NOTIFY;
|
||||||
|
|
||||||
if (of_get_property(node, "wakeup-source", NULL))
|
if (of_get_property(node, "wakeup-source", NULL))
|
||||||
info.flags |= I2C_CLIENT_WAKE;
|
info.flags |= I2C_CLIENT_WAKE;
|
||||||
|
|
||||||
|
@ -3633,7 +3632,7 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!client || !slave_cb) {
|
if (!client || !slave_cb) {
|
||||||
WARN(1, "insufficent data\n");
|
WARN(1, "insufficient data\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -331,7 +331,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
struct i2c_smbus_ioctl_data data_arg;
|
struct i2c_smbus_ioctl_data data_arg;
|
||||||
union i2c_smbus_data temp;
|
union i2c_smbus_data temp = {};
|
||||||
int datasize, res;
|
int datasize, res;
|
||||||
|
|
||||||
if (copy_from_user(&data_arg,
|
if (copy_from_user(&data_arg,
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/miscdevice.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
|
|
@ -1377,6 +1377,12 @@ static int xpad_init_input(struct usb_xpad *xpad)
|
||||||
input_dev->name = xpad->name;
|
input_dev->name = xpad->name;
|
||||||
input_dev->phys = xpad->phys;
|
input_dev->phys = xpad->phys;
|
||||||
usb_to_input_id(xpad->udev, &input_dev->id);
|
usb_to_input_id(xpad->udev, &input_dev->id);
|
||||||
|
|
||||||
|
if (xpad->xtype == XTYPE_XBOX360W) {
|
||||||
|
/* x360w controllers and the receiver have different ids */
|
||||||
|
input_dev->id.product = 0x02a1;
|
||||||
|
}
|
||||||
|
|
||||||
input_dev->dev.parent = &xpad->intf->dev;
|
input_dev->dev.parent = &xpad->intf->dev;
|
||||||
|
|
||||||
input_set_drvdata(input_dev, xpad);
|
input_set_drvdata(input_dev, xpad);
|
||||||
|
|
|
@ -136,7 +136,6 @@ static const struct i2c_device_id adxl34x_id[] = {
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(i2c, adxl34x_id);
|
MODULE_DEVICE_TABLE(i2c, adxl34x_id);
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
|
||||||
static const struct of_device_id adxl34x_of_id[] = {
|
static const struct of_device_id adxl34x_of_id[] = {
|
||||||
/*
|
/*
|
||||||
* The ADXL346 is backward-compatible with the ADXL345. Differences are
|
* The ADXL346 is backward-compatible with the ADXL345. Differences are
|
||||||
|
@ -153,13 +152,12 @@ static const struct of_device_id adxl34x_of_id[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(of, adxl34x_of_id);
|
MODULE_DEVICE_TABLE(of, adxl34x_of_id);
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct i2c_driver adxl34x_driver = {
|
static struct i2c_driver adxl34x_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "adxl34x",
|
.name = "adxl34x",
|
||||||
.pm = &adxl34x_i2c_pm,
|
.pm = &adxl34x_i2c_pm,
|
||||||
.of_match_table = of_match_ptr(adxl34x_of_id),
|
.of_match_table = adxl34x_of_id,
|
||||||
},
|
},
|
||||||
.probe = adxl34x_i2c_probe,
|
.probe = adxl34x_i2c_probe,
|
||||||
.remove = adxl34x_i2c_remove,
|
.remove = adxl34x_i2c_remove,
|
||||||
|
|
|
@ -114,7 +114,7 @@ enum SS4_PACKET_ID {
|
||||||
(_b[1] & 0x7F) \
|
(_b[1] & 0x7F) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define SS4_TS_Y_V2(_b) (s8)( \
|
#define SS4_TS_Y_V2(_b) -(s8)( \
|
||||||
((_b[3] & 0x01) << 7) | \
|
((_b[3] & 0x01) << 7) | \
|
||||||
(_b[2] & 0x7F) \
|
(_b[2] & 0x7F) \
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
* after soft reset, we should wait for 1 ms
|
* after soft reset, we should wait for 1 ms
|
||||||
* before the device becomes operational
|
* before the device becomes operational
|
||||||
*/
|
*/
|
||||||
#define SOFT_RESET_DELAY_MS 3
|
#define SOFT_RESET_DELAY_US 3000
|
||||||
/* and after hard reset, we should wait for max 500ms */
|
/* and after hard reset, we should wait for max 500ms */
|
||||||
#define HARD_RESET_DELAY_MS 500
|
#define HARD_RESET_DELAY_MS 500
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ static int synaptics_i2c_reset_config(struct i2c_client *client)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&client->dev, "Unable to reset device\n");
|
dev_err(&client->dev, "Unable to reset device\n");
|
||||||
} else {
|
} else {
|
||||||
msleep(SOFT_RESET_DELAY_MS);
|
usleep_range(SOFT_RESET_DELAY_US, SOFT_RESET_DELAY_US + 100);
|
||||||
ret = synaptics_i2c_config(client);
|
ret = synaptics_i2c_config(client);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(&client->dev, "Unable to config device\n");
|
dev_err(&client->dev, "Unable to config device\n");
|
||||||
|
|
|
@ -41,7 +41,8 @@ config RMI4_SMB
|
||||||
|
|
||||||
config RMI4_F03
|
config RMI4_F03
|
||||||
bool "RMI4 Function 03 (PS2 Guest)"
|
bool "RMI4 Function 03 (PS2 Guest)"
|
||||||
depends on RMI4_CORE && SERIO
|
depends on RMI4_CORE
|
||||||
|
depends on SERIO=y || RMI4_CORE=SERIO
|
||||||
help
|
help
|
||||||
Say Y here if you want to add support for RMI4 function 03.
|
Say Y here if you want to add support for RMI4 function 03.
|
||||||
|
|
||||||
|
|
|
@ -211,6 +211,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
|
||||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
|
DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -914,9 +914,9 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
|
||||||
|
|
||||||
case QUEUE_HEADER_NORMAL:
|
case QUEUE_HEADER_NORMAL:
|
||||||
report_count = ts->buf[FW_HDR_COUNT];
|
report_count = ts->buf[FW_HDR_COUNT];
|
||||||
if (report_count > 3) {
|
if (report_count == 0 || report_count > 3) {
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"too large report count: %*ph\n",
|
"bad report count: %*ph\n",
|
||||||
HEADER_SIZE, ts->buf);
|
HEADER_SIZE, ts->buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,7 @@ extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
|
||||||
int is_new);
|
int is_new);
|
||||||
struct md_cluster_info;
|
struct md_cluster_info;
|
||||||
|
|
||||||
|
/* change UNSUPPORTED_MDDEV_FLAGS for each array type if new flag is added */
|
||||||
enum mddev_flags {
|
enum mddev_flags {
|
||||||
MD_ARRAY_FIRST_USE, /* First use of array, needs initialization */
|
MD_ARRAY_FIRST_USE, /* First use of array, needs initialization */
|
||||||
MD_CLOSING, /* If set, we are closing the array, do not open
|
MD_CLOSING, /* If set, we are closing the array, do not open
|
||||||
|
@ -702,4 +703,11 @@ static inline int mddev_is_clustered(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
return mddev->cluster_info && mddev->bitmap_info.nodes > 1;
|
return mddev->cluster_info && mddev->bitmap_info.nodes > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clear unsupported mddev_flags */
|
||||||
|
static inline void mddev_clear_unsupported_flags(struct mddev *mddev,
|
||||||
|
unsigned long unsupported_flags)
|
||||||
|
{
|
||||||
|
mddev->flags &= ~unsupported_flags;
|
||||||
|
}
|
||||||
#endif /* _MD_MD_H */
|
#endif /* _MD_MD_H */
|
||||||
|
|
|
@ -26,6 +26,11 @@
|
||||||
#include "raid0.h"
|
#include "raid0.h"
|
||||||
#include "raid5.h"
|
#include "raid5.h"
|
||||||
|
|
||||||
|
#define UNSUPPORTED_MDDEV_FLAGS \
|
||||||
|
((1L << MD_HAS_JOURNAL) | \
|
||||||
|
(1L << MD_JOURNAL_CLEAN) | \
|
||||||
|
(1L << MD_FAILFAST_SUPPORTED))
|
||||||
|
|
||||||
static int raid0_congested(struct mddev *mddev, int bits)
|
static int raid0_congested(struct mddev *mddev, int bits)
|
||||||
{
|
{
|
||||||
struct r0conf *conf = mddev->private;
|
struct r0conf *conf = mddev->private;
|
||||||
|
@ -539,8 +544,7 @@ static void *raid0_takeover_raid45(struct mddev *mddev)
|
||||||
mddev->delta_disks = -1;
|
mddev->delta_disks = -1;
|
||||||
/* make sure it will be not marked as dirty */
|
/* make sure it will be not marked as dirty */
|
||||||
mddev->recovery_cp = MaxSector;
|
mddev->recovery_cp = MaxSector;
|
||||||
clear_bit(MD_HAS_JOURNAL, &mddev->flags);
|
mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
|
||||||
clear_bit(MD_JOURNAL_CLEAN, &mddev->flags);
|
|
||||||
|
|
||||||
create_strip_zones(mddev, &priv_conf);
|
create_strip_zones(mddev, &priv_conf);
|
||||||
|
|
||||||
|
@ -583,7 +587,7 @@ static void *raid0_takeover_raid10(struct mddev *mddev)
|
||||||
mddev->degraded = 0;
|
mddev->degraded = 0;
|
||||||
/* make sure it will be not marked as dirty */
|
/* make sure it will be not marked as dirty */
|
||||||
mddev->recovery_cp = MaxSector;
|
mddev->recovery_cp = MaxSector;
|
||||||
clear_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
|
mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
|
||||||
|
|
||||||
create_strip_zones(mddev, &priv_conf);
|
create_strip_zones(mddev, &priv_conf);
|
||||||
return priv_conf;
|
return priv_conf;
|
||||||
|
@ -626,7 +630,7 @@ static void *raid0_takeover_raid1(struct mddev *mddev)
|
||||||
mddev->raid_disks = 1;
|
mddev->raid_disks = 1;
|
||||||
/* make sure it will be not marked as dirty */
|
/* make sure it will be not marked as dirty */
|
||||||
mddev->recovery_cp = MaxSector;
|
mddev->recovery_cp = MaxSector;
|
||||||
clear_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
|
mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
|
||||||
|
|
||||||
create_strip_zones(mddev, &priv_conf);
|
create_strip_zones(mddev, &priv_conf);
|
||||||
return priv_conf;
|
return priv_conf;
|
||||||
|
|
|
@ -42,6 +42,10 @@
|
||||||
#include "raid1.h"
|
#include "raid1.h"
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
|
||||||
|
#define UNSUPPORTED_MDDEV_FLAGS \
|
||||||
|
((1L << MD_HAS_JOURNAL) | \
|
||||||
|
(1L << MD_JOURNAL_CLEAN))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of guaranteed r1bios in case of extreme VM load:
|
* Number of guaranteed r1bios in case of extreme VM load:
|
||||||
*/
|
*/
|
||||||
|
@ -1066,17 +1070,107 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
|
||||||
kfree(plug);
|
kfree(plug);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raid1_make_request(struct mddev *mddev, struct bio * bio)
|
static void raid1_read_request(struct mddev *mddev, struct bio *bio,
|
||||||
|
struct r1bio *r1_bio)
|
||||||
{
|
{
|
||||||
struct r1conf *conf = mddev->private;
|
struct r1conf *conf = mddev->private;
|
||||||
struct raid1_info *mirror;
|
struct raid1_info *mirror;
|
||||||
struct r1bio *r1_bio;
|
|
||||||
struct bio *read_bio;
|
struct bio *read_bio;
|
||||||
|
struct bitmap *bitmap = mddev->bitmap;
|
||||||
|
const int op = bio_op(bio);
|
||||||
|
const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
|
||||||
|
int sectors_handled;
|
||||||
|
int max_sectors;
|
||||||
|
int rdisk;
|
||||||
|
|
||||||
|
wait_barrier(conf, bio);
|
||||||
|
|
||||||
|
read_again:
|
||||||
|
rdisk = read_balance(conf, r1_bio, &max_sectors);
|
||||||
|
|
||||||
|
if (rdisk < 0) {
|
||||||
|
/* couldn't find anywhere to read from */
|
||||||
|
raid_end_bio_io(r1_bio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mirror = conf->mirrors + rdisk;
|
||||||
|
|
||||||
|
if (test_bit(WriteMostly, &mirror->rdev->flags) &&
|
||||||
|
bitmap) {
|
||||||
|
/*
|
||||||
|
* Reading from a write-mostly device must take care not to
|
||||||
|
* over-take any writes that are 'behind'
|
||||||
|
*/
|
||||||
|
raid1_log(mddev, "wait behind writes");
|
||||||
|
wait_event(bitmap->behind_wait,
|
||||||
|
atomic_read(&bitmap->behind_writes) == 0);
|
||||||
|
}
|
||||||
|
r1_bio->read_disk = rdisk;
|
||||||
|
r1_bio->start_next_window = 0;
|
||||||
|
|
||||||
|
read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
|
||||||
|
bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector,
|
||||||
|
max_sectors);
|
||||||
|
|
||||||
|
r1_bio->bios[rdisk] = read_bio;
|
||||||
|
|
||||||
|
read_bio->bi_iter.bi_sector = r1_bio->sector +
|
||||||
|
mirror->rdev->data_offset;
|
||||||
|
read_bio->bi_bdev = mirror->rdev->bdev;
|
||||||
|
read_bio->bi_end_io = raid1_end_read_request;
|
||||||
|
bio_set_op_attrs(read_bio, op, do_sync);
|
||||||
|
if (test_bit(FailFast, &mirror->rdev->flags) &&
|
||||||
|
test_bit(R1BIO_FailFast, &r1_bio->state))
|
||||||
|
read_bio->bi_opf |= MD_FAILFAST;
|
||||||
|
read_bio->bi_private = r1_bio;
|
||||||
|
|
||||||
|
if (mddev->gendisk)
|
||||||
|
trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
|
||||||
|
read_bio, disk_devt(mddev->gendisk),
|
||||||
|
r1_bio->sector);
|
||||||
|
|
||||||
|
if (max_sectors < r1_bio->sectors) {
|
||||||
|
/*
|
||||||
|
* could not read all from this device, so we will need another
|
||||||
|
* r1_bio.
|
||||||
|
*/
|
||||||
|
sectors_handled = (r1_bio->sector + max_sectors
|
||||||
|
- bio->bi_iter.bi_sector);
|
||||||
|
r1_bio->sectors = max_sectors;
|
||||||
|
spin_lock_irq(&conf->device_lock);
|
||||||
|
if (bio->bi_phys_segments == 0)
|
||||||
|
bio->bi_phys_segments = 2;
|
||||||
|
else
|
||||||
|
bio->bi_phys_segments++;
|
||||||
|
spin_unlock_irq(&conf->device_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cannot call generic_make_request directly as that will be
|
||||||
|
* queued in __make_request and subsequent mempool_alloc might
|
||||||
|
* block waiting for it. So hand bio over to raid1d.
|
||||||
|
*/
|
||||||
|
reschedule_retry(r1_bio);
|
||||||
|
|
||||||
|
r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
|
||||||
|
|
||||||
|
r1_bio->master_bio = bio;
|
||||||
|
r1_bio->sectors = bio_sectors(bio) - sectors_handled;
|
||||||
|
r1_bio->state = 0;
|
||||||
|
r1_bio->mddev = mddev;
|
||||||
|
r1_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
|
||||||
|
goto read_again;
|
||||||
|
} else
|
||||||
|
generic_make_request(read_bio);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raid1_write_request(struct mddev *mddev, struct bio *bio,
|
||||||
|
struct r1bio *r1_bio)
|
||||||
|
{
|
||||||
|
struct r1conf *conf = mddev->private;
|
||||||
int i, disks;
|
int i, disks;
|
||||||
struct bitmap *bitmap;
|
struct bitmap *bitmap = mddev->bitmap;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
const int op = bio_op(bio);
|
const int op = bio_op(bio);
|
||||||
const int rw = bio_data_dir(bio);
|
|
||||||
const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
|
const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
|
||||||
const unsigned long do_flush_fua = (bio->bi_opf &
|
const unsigned long do_flush_fua = (bio->bi_opf &
|
||||||
(REQ_PREFLUSH | REQ_FUA));
|
(REQ_PREFLUSH | REQ_FUA));
|
||||||
|
@ -1096,15 +1190,15 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio)
|
||||||
|
|
||||||
md_write_start(mddev, bio); /* wait on superblock update early */
|
md_write_start(mddev, bio); /* wait on superblock update early */
|
||||||
|
|
||||||
if (bio_data_dir(bio) == WRITE &&
|
if ((bio_end_sector(bio) > mddev->suspend_lo &&
|
||||||
((bio_end_sector(bio) > mddev->suspend_lo &&
|
|
||||||
bio->bi_iter.bi_sector < mddev->suspend_hi) ||
|
bio->bi_iter.bi_sector < mddev->suspend_hi) ||
|
||||||
(mddev_is_clustered(mddev) &&
|
(mddev_is_clustered(mddev) &&
|
||||||
md_cluster_ops->area_resyncing(mddev, WRITE,
|
md_cluster_ops->area_resyncing(mddev, WRITE,
|
||||||
bio->bi_iter.bi_sector, bio_end_sector(bio))))) {
|
bio->bi_iter.bi_sector, bio_end_sector(bio)))) {
|
||||||
/* As the suspend_* range is controlled by
|
|
||||||
* userspace, we want an interruptible
|
/*
|
||||||
* wait.
|
* As the suspend_* range is controlled by userspace, we want
|
||||||
|
* an interruptible wait.
|
||||||
*/
|
*/
|
||||||
DEFINE_WAIT(w);
|
DEFINE_WAIT(w);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1115,128 +1209,15 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio)
|
||||||
bio->bi_iter.bi_sector >= mddev->suspend_hi ||
|
bio->bi_iter.bi_sector >= mddev->suspend_hi ||
|
||||||
(mddev_is_clustered(mddev) &&
|
(mddev_is_clustered(mddev) &&
|
||||||
!md_cluster_ops->area_resyncing(mddev, WRITE,
|
!md_cluster_ops->area_resyncing(mddev, WRITE,
|
||||||
bio->bi_iter.bi_sector, bio_end_sector(bio))))
|
bio->bi_iter.bi_sector,
|
||||||
|
bio_end_sector(bio))))
|
||||||
break;
|
break;
|
||||||
schedule();
|
schedule();
|
||||||
}
|
}
|
||||||
finish_wait(&conf->wait_barrier, &w);
|
finish_wait(&conf->wait_barrier, &w);
|
||||||
}
|
}
|
||||||
|
|
||||||
start_next_window = wait_barrier(conf, bio);
|
start_next_window = wait_barrier(conf, bio);
|
||||||
|
|
||||||
bitmap = mddev->bitmap;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* make_request() can abort the operation when read-ahead is being
|
|
||||||
* used and no empty request is available.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
|
|
||||||
|
|
||||||
r1_bio->master_bio = bio;
|
|
||||||
r1_bio->sectors = bio_sectors(bio);
|
|
||||||
r1_bio->state = 0;
|
|
||||||
r1_bio->mddev = mddev;
|
|
||||||
r1_bio->sector = bio->bi_iter.bi_sector;
|
|
||||||
|
|
||||||
/* We might need to issue multiple reads to different
|
|
||||||
* devices if there are bad blocks around, so we keep
|
|
||||||
* track of the number of reads in bio->bi_phys_segments.
|
|
||||||
* If this is 0, there is only one r1_bio and no locking
|
|
||||||
* will be needed when requests complete. If it is
|
|
||||||
* non-zero, then it is the number of not-completed requests.
|
|
||||||
*/
|
|
||||||
bio->bi_phys_segments = 0;
|
|
||||||
bio_clear_flag(bio, BIO_SEG_VALID);
|
|
||||||
|
|
||||||
if (rw == READ) {
|
|
||||||
/*
|
|
||||||
* read balancing logic:
|
|
||||||
*/
|
|
||||||
int rdisk;
|
|
||||||
|
|
||||||
read_again:
|
|
||||||
rdisk = read_balance(conf, r1_bio, &max_sectors);
|
|
||||||
|
|
||||||
if (rdisk < 0) {
|
|
||||||
/* couldn't find anywhere to read from */
|
|
||||||
raid_end_bio_io(r1_bio);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mirror = conf->mirrors + rdisk;
|
|
||||||
|
|
||||||
if (test_bit(WriteMostly, &mirror->rdev->flags) &&
|
|
||||||
bitmap) {
|
|
||||||
/* Reading from a write-mostly device must
|
|
||||||
* take care not to over-take any writes
|
|
||||||
* that are 'behind'
|
|
||||||
*/
|
|
||||||
raid1_log(mddev, "wait behind writes");
|
|
||||||
wait_event(bitmap->behind_wait,
|
|
||||||
atomic_read(&bitmap->behind_writes) == 0);
|
|
||||||
}
|
|
||||||
r1_bio->read_disk = rdisk;
|
|
||||||
r1_bio->start_next_window = 0;
|
|
||||||
|
|
||||||
read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
|
|
||||||
bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector,
|
|
||||||
max_sectors);
|
|
||||||
|
|
||||||
r1_bio->bios[rdisk] = read_bio;
|
|
||||||
|
|
||||||
read_bio->bi_iter.bi_sector = r1_bio->sector +
|
|
||||||
mirror->rdev->data_offset;
|
|
||||||
read_bio->bi_bdev = mirror->rdev->bdev;
|
|
||||||
read_bio->bi_end_io = raid1_end_read_request;
|
|
||||||
bio_set_op_attrs(read_bio, op, do_sync);
|
|
||||||
if (test_bit(FailFast, &mirror->rdev->flags) &&
|
|
||||||
test_bit(R1BIO_FailFast, &r1_bio->state))
|
|
||||||
read_bio->bi_opf |= MD_FAILFAST;
|
|
||||||
read_bio->bi_private = r1_bio;
|
|
||||||
|
|
||||||
if (mddev->gendisk)
|
|
||||||
trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
|
|
||||||
read_bio, disk_devt(mddev->gendisk),
|
|
||||||
r1_bio->sector);
|
|
||||||
|
|
||||||
if (max_sectors < r1_bio->sectors) {
|
|
||||||
/* could not read all from this device, so we will
|
|
||||||
* need another r1_bio.
|
|
||||||
*/
|
|
||||||
|
|
||||||
sectors_handled = (r1_bio->sector + max_sectors
|
|
||||||
- bio->bi_iter.bi_sector);
|
|
||||||
r1_bio->sectors = max_sectors;
|
|
||||||
spin_lock_irq(&conf->device_lock);
|
|
||||||
if (bio->bi_phys_segments == 0)
|
|
||||||
bio->bi_phys_segments = 2;
|
|
||||||
else
|
|
||||||
bio->bi_phys_segments++;
|
|
||||||
spin_unlock_irq(&conf->device_lock);
|
|
||||||
/* Cannot call generic_make_request directly
|
|
||||||
* as that will be queued in __make_request
|
|
||||||
* and subsequent mempool_alloc might block waiting
|
|
||||||
* for it. So hand bio over to raid1d.
|
|
||||||
*/
|
|
||||||
reschedule_retry(r1_bio);
|
|
||||||
|
|
||||||
r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
|
|
||||||
|
|
||||||
r1_bio->master_bio = bio;
|
|
||||||
r1_bio->sectors = bio_sectors(bio) - sectors_handled;
|
|
||||||
r1_bio->state = 0;
|
|
||||||
r1_bio->mddev = mddev;
|
|
||||||
r1_bio->sector = bio->bi_iter.bi_sector +
|
|
||||||
sectors_handled;
|
|
||||||
goto read_again;
|
|
||||||
} else
|
|
||||||
generic_make_request(read_bio);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* WRITE:
|
|
||||||
*/
|
|
||||||
if (conf->pending_count >= max_queued_requests) {
|
if (conf->pending_count >= max_queued_requests) {
|
||||||
md_wakeup_thread(mddev->thread);
|
md_wakeup_thread(mddev->thread);
|
||||||
raid1_log(mddev, "wait queued");
|
raid1_log(mddev, "wait queued");
|
||||||
|
@ -1280,8 +1261,7 @@ read_again:
|
||||||
int bad_sectors;
|
int bad_sectors;
|
||||||
int is_bad;
|
int is_bad;
|
||||||
|
|
||||||
is_bad = is_badblock(rdev, r1_bio->sector,
|
is_bad = is_badblock(rdev, r1_bio->sector, max_sectors,
|
||||||
max_sectors,
|
|
||||||
&first_bad, &bad_sectors);
|
&first_bad, &bad_sectors);
|
||||||
if (is_bad < 0) {
|
if (is_bad < 0) {
|
||||||
/* mustn't write here until the bad block is
|
/* mustn't write here until the bad block is
|
||||||
|
@ -1370,7 +1350,8 @@ read_again:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
|
mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
|
||||||
bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector, max_sectors);
|
bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector,
|
||||||
|
max_sectors);
|
||||||
|
|
||||||
if (first_clone) {
|
if (first_clone) {
|
||||||
/* do behind I/O ?
|
/* do behind I/O ?
|
||||||
|
@ -1464,6 +1445,40 @@ read_again:
|
||||||
wake_up(&conf->wait_barrier);
|
wake_up(&conf->wait_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void raid1_make_request(struct mddev *mddev, struct bio *bio)
|
||||||
|
{
|
||||||
|
struct r1conf *conf = mddev->private;
|
||||||
|
struct r1bio *r1_bio;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_request() can abort the operation when read-ahead is being
|
||||||
|
* used and no empty request is available.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
|
||||||
|
|
||||||
|
r1_bio->master_bio = bio;
|
||||||
|
r1_bio->sectors = bio_sectors(bio);
|
||||||
|
r1_bio->state = 0;
|
||||||
|
r1_bio->mddev = mddev;
|
||||||
|
r1_bio->sector = bio->bi_iter.bi_sector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We might need to issue multiple reads to different devices if there
|
||||||
|
* are bad blocks around, so we keep track of the number of reads in
|
||||||
|
* bio->bi_phys_segments. If this is 0, there is only one r1_bio and
|
||||||
|
* no locking will be needed when requests complete. If it is
|
||||||
|
* non-zero, then it is the number of not-completed requests.
|
||||||
|
*/
|
||||||
|
bio->bi_phys_segments = 0;
|
||||||
|
bio_clear_flag(bio, BIO_SEG_VALID);
|
||||||
|
|
||||||
|
if (bio_data_dir(bio) == READ)
|
||||||
|
raid1_read_request(mddev, bio, r1_bio);
|
||||||
|
else
|
||||||
|
raid1_write_request(mddev, bio, r1_bio);
|
||||||
|
}
|
||||||
|
|
||||||
static void raid1_status(struct seq_file *seq, struct mddev *mddev)
|
static void raid1_status(struct seq_file *seq, struct mddev *mddev)
|
||||||
{
|
{
|
||||||
struct r1conf *conf = mddev->private;
|
struct r1conf *conf = mddev->private;
|
||||||
|
@ -3246,8 +3261,8 @@ static void *raid1_takeover(struct mddev *mddev)
|
||||||
if (!IS_ERR(conf)) {
|
if (!IS_ERR(conf)) {
|
||||||
/* Array must appear to be quiesced */
|
/* Array must appear to be quiesced */
|
||||||
conf->array_frozen = 1;
|
conf->array_frozen = 1;
|
||||||
clear_bit(MD_HAS_JOURNAL, &mddev->flags);
|
mddev_clear_unsupported_flags(mddev,
|
||||||
clear_bit(MD_JOURNAL_CLEAN, &mddev->flags);
|
UNSUPPORTED_MDDEV_FLAGS);
|
||||||
}
|
}
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1087,23 +1087,122 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
|
||||||
kfree(plug);
|
kfree(plug);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __make_request(struct mddev *mddev, struct bio *bio)
|
static void raid10_read_request(struct mddev *mddev, struct bio *bio,
|
||||||
|
struct r10bio *r10_bio)
|
||||||
{
|
{
|
||||||
struct r10conf *conf = mddev->private;
|
struct r10conf *conf = mddev->private;
|
||||||
struct r10bio *r10_bio;
|
|
||||||
struct bio *read_bio;
|
struct bio *read_bio;
|
||||||
|
const int op = bio_op(bio);
|
||||||
|
const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
|
||||||
|
int sectors_handled;
|
||||||
|
int max_sectors;
|
||||||
|
sector_t sectors;
|
||||||
|
struct md_rdev *rdev;
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register the new request and wait if the reconstruction
|
||||||
|
* thread has put up a bar for new requests.
|
||||||
|
* Continue immediately if no resync is active currently.
|
||||||
|
*/
|
||||||
|
wait_barrier(conf);
|
||||||
|
|
||||||
|
sectors = bio_sectors(bio);
|
||||||
|
while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
|
||||||
|
bio->bi_iter.bi_sector < conf->reshape_progress &&
|
||||||
|
bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
|
||||||
|
/*
|
||||||
|
* IO spans the reshape position. Need to wait for reshape to
|
||||||
|
* pass
|
||||||
|
*/
|
||||||
|
raid10_log(conf->mddev, "wait reshape");
|
||||||
|
allow_barrier(conf);
|
||||||
|
wait_event(conf->wait_barrier,
|
||||||
|
conf->reshape_progress <= bio->bi_iter.bi_sector ||
|
||||||
|
conf->reshape_progress >= bio->bi_iter.bi_sector +
|
||||||
|
sectors);
|
||||||
|
wait_barrier(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
read_again:
|
||||||
|
rdev = read_balance(conf, r10_bio, &max_sectors);
|
||||||
|
if (!rdev) {
|
||||||
|
raid_end_bio_io(r10_bio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
slot = r10_bio->read_slot;
|
||||||
|
|
||||||
|
read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
|
||||||
|
bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector,
|
||||||
|
max_sectors);
|
||||||
|
|
||||||
|
r10_bio->devs[slot].bio = read_bio;
|
||||||
|
r10_bio->devs[slot].rdev = rdev;
|
||||||
|
|
||||||
|
read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr +
|
||||||
|
choose_data_offset(r10_bio, rdev);
|
||||||
|
read_bio->bi_bdev = rdev->bdev;
|
||||||
|
read_bio->bi_end_io = raid10_end_read_request;
|
||||||
|
bio_set_op_attrs(read_bio, op, do_sync);
|
||||||
|
if (test_bit(FailFast, &rdev->flags) &&
|
||||||
|
test_bit(R10BIO_FailFast, &r10_bio->state))
|
||||||
|
read_bio->bi_opf |= MD_FAILFAST;
|
||||||
|
read_bio->bi_private = r10_bio;
|
||||||
|
|
||||||
|
if (mddev->gendisk)
|
||||||
|
trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
|
||||||
|
read_bio, disk_devt(mddev->gendisk),
|
||||||
|
r10_bio->sector);
|
||||||
|
if (max_sectors < r10_bio->sectors) {
|
||||||
|
/*
|
||||||
|
* Could not read all from this device, so we will need another
|
||||||
|
* r10_bio.
|
||||||
|
*/
|
||||||
|
sectors_handled = (r10_bio->sector + max_sectors
|
||||||
|
- bio->bi_iter.bi_sector);
|
||||||
|
r10_bio->sectors = max_sectors;
|
||||||
|
spin_lock_irq(&conf->device_lock);
|
||||||
|
if (bio->bi_phys_segments == 0)
|
||||||
|
bio->bi_phys_segments = 2;
|
||||||
|
else
|
||||||
|
bio->bi_phys_segments++;
|
||||||
|
spin_unlock_irq(&conf->device_lock);
|
||||||
|
/*
|
||||||
|
* Cannot call generic_make_request directly as that will be
|
||||||
|
* queued in __generic_make_request and subsequent
|
||||||
|
* mempool_alloc might block waiting for it. so hand bio over
|
||||||
|
* to raid10d.
|
||||||
|
*/
|
||||||
|
reschedule_retry(r10_bio);
|
||||||
|
|
||||||
|
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
|
||||||
|
|
||||||
|
r10_bio->master_bio = bio;
|
||||||
|
r10_bio->sectors = bio_sectors(bio) - sectors_handled;
|
||||||
|
r10_bio->state = 0;
|
||||||
|
r10_bio->mddev = mddev;
|
||||||
|
r10_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
|
||||||
|
goto read_again;
|
||||||
|
} else
|
||||||
|
generic_make_request(read_bio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raid10_write_request(struct mddev *mddev, struct bio *bio,
|
||||||
|
struct r10bio *r10_bio)
|
||||||
|
{
|
||||||
|
struct r10conf *conf = mddev->private;
|
||||||
int i;
|
int i;
|
||||||
const int op = bio_op(bio);
|
const int op = bio_op(bio);
|
||||||
const int rw = bio_data_dir(bio);
|
|
||||||
const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
|
const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
|
||||||
const unsigned long do_fua = (bio->bi_opf & REQ_FUA);
|
const unsigned long do_fua = (bio->bi_opf & REQ_FUA);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct md_rdev *blocked_rdev;
|
struct md_rdev *blocked_rdev;
|
||||||
struct blk_plug_cb *cb;
|
struct blk_plug_cb *cb;
|
||||||
struct raid10_plug_cb *plug = NULL;
|
struct raid10_plug_cb *plug = NULL;
|
||||||
|
sector_t sectors;
|
||||||
int sectors_handled;
|
int sectors_handled;
|
||||||
int max_sectors;
|
int max_sectors;
|
||||||
int sectors;
|
|
||||||
|
|
||||||
md_write_start(mddev, bio);
|
md_write_start(mddev, bio);
|
||||||
|
|
||||||
|
@ -1118,8 +1217,9 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
|
||||||
while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
|
while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
|
||||||
bio->bi_iter.bi_sector < conf->reshape_progress &&
|
bio->bi_iter.bi_sector < conf->reshape_progress &&
|
||||||
bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
|
bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
|
||||||
/* IO spans the reshape position. Need to wait for
|
/*
|
||||||
* reshape to pass
|
* IO spans the reshape position. Need to wait for reshape to
|
||||||
|
* pass
|
||||||
*/
|
*/
|
||||||
raid10_log(conf->mddev, "wait reshape");
|
raid10_log(conf->mddev, "wait reshape");
|
||||||
allow_barrier(conf);
|
allow_barrier(conf);
|
||||||
|
@ -1129,8 +1229,8 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
|
||||||
sectors);
|
sectors);
|
||||||
wait_barrier(conf);
|
wait_barrier(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
|
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
|
||||||
bio_data_dir(bio) == WRITE &&
|
|
||||||
(mddev->reshape_backwards
|
(mddev->reshape_backwards
|
||||||
? (bio->bi_iter.bi_sector < conf->reshape_safe &&
|
? (bio->bi_iter.bi_sector < conf->reshape_safe &&
|
||||||
bio->bi_iter.bi_sector + sectors > conf->reshape_progress)
|
bio->bi_iter.bi_sector + sectors > conf->reshape_progress)
|
||||||
|
@ -1148,98 +1248,6 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
|
||||||
conf->reshape_safe = mddev->reshape_position;
|
conf->reshape_safe = mddev->reshape_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
|
|
||||||
|
|
||||||
r10_bio->master_bio = bio;
|
|
||||||
r10_bio->sectors = sectors;
|
|
||||||
|
|
||||||
r10_bio->mddev = mddev;
|
|
||||||
r10_bio->sector = bio->bi_iter.bi_sector;
|
|
||||||
r10_bio->state = 0;
|
|
||||||
|
|
||||||
/* We might need to issue multiple reads to different
|
|
||||||
* devices if there are bad blocks around, so we keep
|
|
||||||
* track of the number of reads in bio->bi_phys_segments.
|
|
||||||
* If this is 0, there is only one r10_bio and no locking
|
|
||||||
* will be needed when the request completes. If it is
|
|
||||||
* non-zero, then it is the number of not-completed requests.
|
|
||||||
*/
|
|
||||||
bio->bi_phys_segments = 0;
|
|
||||||
bio_clear_flag(bio, BIO_SEG_VALID);
|
|
||||||
|
|
||||||
if (rw == READ) {
|
|
||||||
/*
|
|
||||||
* read balancing logic:
|
|
||||||
*/
|
|
||||||
struct md_rdev *rdev;
|
|
||||||
int slot;
|
|
||||||
|
|
||||||
read_again:
|
|
||||||
rdev = read_balance(conf, r10_bio, &max_sectors);
|
|
||||||
if (!rdev) {
|
|
||||||
raid_end_bio_io(r10_bio);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
slot = r10_bio->read_slot;
|
|
||||||
|
|
||||||
read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
|
|
||||||
bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector,
|
|
||||||
max_sectors);
|
|
||||||
|
|
||||||
r10_bio->devs[slot].bio = read_bio;
|
|
||||||
r10_bio->devs[slot].rdev = rdev;
|
|
||||||
|
|
||||||
read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr +
|
|
||||||
choose_data_offset(r10_bio, rdev);
|
|
||||||
read_bio->bi_bdev = rdev->bdev;
|
|
||||||
read_bio->bi_end_io = raid10_end_read_request;
|
|
||||||
bio_set_op_attrs(read_bio, op, do_sync);
|
|
||||||
if (test_bit(FailFast, &rdev->flags) &&
|
|
||||||
test_bit(R10BIO_FailFast, &r10_bio->state))
|
|
||||||
read_bio->bi_opf |= MD_FAILFAST;
|
|
||||||
read_bio->bi_private = r10_bio;
|
|
||||||
|
|
||||||
if (mddev->gendisk)
|
|
||||||
trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
|
|
||||||
read_bio, disk_devt(mddev->gendisk),
|
|
||||||
r10_bio->sector);
|
|
||||||
if (max_sectors < r10_bio->sectors) {
|
|
||||||
/* Could not read all from this device, so we will
|
|
||||||
* need another r10_bio.
|
|
||||||
*/
|
|
||||||
sectors_handled = (r10_bio->sector + max_sectors
|
|
||||||
- bio->bi_iter.bi_sector);
|
|
||||||
r10_bio->sectors = max_sectors;
|
|
||||||
spin_lock_irq(&conf->device_lock);
|
|
||||||
if (bio->bi_phys_segments == 0)
|
|
||||||
bio->bi_phys_segments = 2;
|
|
||||||
else
|
|
||||||
bio->bi_phys_segments++;
|
|
||||||
spin_unlock_irq(&conf->device_lock);
|
|
||||||
/* Cannot call generic_make_request directly
|
|
||||||
* as that will be queued in __generic_make_request
|
|
||||||
* and subsequent mempool_alloc might block
|
|
||||||
* waiting for it. so hand bio over to raid10d.
|
|
||||||
*/
|
|
||||||
reschedule_retry(r10_bio);
|
|
||||||
|
|
||||||
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
|
|
||||||
|
|
||||||
r10_bio->master_bio = bio;
|
|
||||||
r10_bio->sectors = bio_sectors(bio) - sectors_handled;
|
|
||||||
r10_bio->state = 0;
|
|
||||||
r10_bio->mddev = mddev;
|
|
||||||
r10_bio->sector = bio->bi_iter.bi_sector +
|
|
||||||
sectors_handled;
|
|
||||||
goto read_again;
|
|
||||||
} else
|
|
||||||
generic_make_request(read_bio);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* WRITE:
|
|
||||||
*/
|
|
||||||
if (conf->pending_count >= max_queued_requests) {
|
if (conf->pending_count >= max_queued_requests) {
|
||||||
md_wakeup_thread(mddev->thread);
|
md_wakeup_thread(mddev->thread);
|
||||||
raid10_log(mddev, "wait queued");
|
raid10_log(mddev, "wait queued");
|
||||||
|
@ -1300,8 +1308,7 @@ retry_write:
|
||||||
int bad_sectors;
|
int bad_sectors;
|
||||||
int is_bad;
|
int is_bad;
|
||||||
|
|
||||||
is_bad = is_badblock(rdev, dev_sector,
|
is_bad = is_badblock(rdev, dev_sector, max_sectors,
|
||||||
max_sectors,
|
|
||||||
&first_bad, &bad_sectors);
|
&first_bad, &bad_sectors);
|
||||||
if (is_bad < 0) {
|
if (is_bad < 0) {
|
||||||
/* Mustn't write here until the bad block
|
/* Mustn't write here until the bad block
|
||||||
|
@ -1405,8 +1412,7 @@ retry_write:
|
||||||
r10_bio->devs[i].bio = mbio;
|
r10_bio->devs[i].bio = mbio;
|
||||||
|
|
||||||
mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr+
|
mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr+
|
||||||
choose_data_offset(r10_bio,
|
choose_data_offset(r10_bio, rdev));
|
||||||
rdev));
|
|
||||||
mbio->bi_bdev = rdev->bdev;
|
mbio->bi_bdev = rdev->bdev;
|
||||||
mbio->bi_end_io = raid10_end_write_request;
|
mbio->bi_end_io = raid10_end_write_request;
|
||||||
bio_set_op_attrs(mbio, op, do_sync | do_fua);
|
bio_set_op_attrs(mbio, op, do_sync | do_fua);
|
||||||
|
@ -1457,8 +1463,7 @@ retry_write:
|
||||||
r10_bio->devs[i].repl_bio = mbio;
|
r10_bio->devs[i].repl_bio = mbio;
|
||||||
|
|
||||||
mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr +
|
mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr +
|
||||||
choose_data_offset(
|
choose_data_offset(r10_bio, rdev));
|
||||||
r10_bio, rdev));
|
|
||||||
mbio->bi_bdev = rdev->bdev;
|
mbio->bi_bdev = rdev->bdev;
|
||||||
mbio->bi_end_io = raid10_end_write_request;
|
mbio->bi_end_io = raid10_end_write_request;
|
||||||
bio_set_op_attrs(mbio, op, do_sync | do_fua);
|
bio_set_op_attrs(mbio, op, do_sync | do_fua);
|
||||||
|
@ -1503,6 +1508,36 @@ retry_write:
|
||||||
one_write_done(r10_bio);
|
one_write_done(r10_bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __make_request(struct mddev *mddev, struct bio *bio)
|
||||||
|
{
|
||||||
|
struct r10conf *conf = mddev->private;
|
||||||
|
struct r10bio *r10_bio;
|
||||||
|
|
||||||
|
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
|
||||||
|
|
||||||
|
r10_bio->master_bio = bio;
|
||||||
|
r10_bio->sectors = bio_sectors(bio);
|
||||||
|
|
||||||
|
r10_bio->mddev = mddev;
|
||||||
|
r10_bio->sector = bio->bi_iter.bi_sector;
|
||||||
|
r10_bio->state = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We might need to issue multiple reads to different devices if there
|
||||||
|
* are bad blocks around, so we keep track of the number of reads in
|
||||||
|
* bio->bi_phys_segments. If this is 0, there is only one r10_bio and
|
||||||
|
* no locking will be needed when the request completes. If it is
|
||||||
|
* non-zero, then it is the number of not-completed requests.
|
||||||
|
*/
|
||||||
|
bio->bi_phys_segments = 0;
|
||||||
|
bio_clear_flag(bio, BIO_SEG_VALID);
|
||||||
|
|
||||||
|
if (bio_data_dir(bio) == READ)
|
||||||
|
raid10_read_request(mddev, bio, r10_bio);
|
||||||
|
else
|
||||||
|
raid10_write_request(mddev, bio, r10_bio);
|
||||||
|
}
|
||||||
|
|
||||||
static void raid10_make_request(struct mddev *mddev, struct bio *bio)
|
static void raid10_make_request(struct mddev *mddev, struct bio *bio)
|
||||||
{
|
{
|
||||||
struct r10conf *conf = mddev->private;
|
struct r10conf *conf = mddev->private;
|
||||||
|
|
|
@ -1682,8 +1682,7 @@ out:
|
||||||
|
|
||||||
static struct stripe_head *
|
static struct stripe_head *
|
||||||
r5c_recovery_alloc_stripe(struct r5conf *conf,
|
r5c_recovery_alloc_stripe(struct r5conf *conf,
|
||||||
sector_t stripe_sect,
|
sector_t stripe_sect)
|
||||||
sector_t log_start)
|
|
||||||
{
|
{
|
||||||
struct stripe_head *sh;
|
struct stripe_head *sh;
|
||||||
|
|
||||||
|
@ -1692,7 +1691,6 @@ r5c_recovery_alloc_stripe(struct r5conf *conf,
|
||||||
return NULL; /* no more stripe available */
|
return NULL; /* no more stripe available */
|
||||||
|
|
||||||
r5l_recovery_reset_stripe(sh);
|
r5l_recovery_reset_stripe(sh);
|
||||||
sh->log_start = log_start;
|
|
||||||
|
|
||||||
return sh;
|
return sh;
|
||||||
}
|
}
|
||||||
|
@ -1862,7 +1860,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
|
||||||
stripe_sect);
|
stripe_sect);
|
||||||
|
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
sh = r5c_recovery_alloc_stripe(conf, stripe_sect, ctx->pos);
|
sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
|
||||||
/*
|
/*
|
||||||
* cannot get stripe from raid5_get_active_stripe
|
* cannot get stripe from raid5_get_active_stripe
|
||||||
* try replay some stripes
|
* try replay some stripes
|
||||||
|
@ -1871,7 +1869,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
|
||||||
r5c_recovery_replay_stripes(
|
r5c_recovery_replay_stripes(
|
||||||
cached_stripe_list, ctx);
|
cached_stripe_list, ctx);
|
||||||
sh = r5c_recovery_alloc_stripe(
|
sh = r5c_recovery_alloc_stripe(
|
||||||
conf, stripe_sect, ctx->pos);
|
conf, stripe_sect);
|
||||||
}
|
}
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
|
pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
|
||||||
|
@ -1879,8 +1877,8 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
|
||||||
conf->min_nr_stripes * 2);
|
conf->min_nr_stripes * 2);
|
||||||
raid5_set_cache_size(mddev,
|
raid5_set_cache_size(mddev,
|
||||||
conf->min_nr_stripes * 2);
|
conf->min_nr_stripes * 2);
|
||||||
sh = r5c_recovery_alloc_stripe(
|
sh = r5c_recovery_alloc_stripe(conf,
|
||||||
conf, stripe_sect, ctx->pos);
|
stripe_sect);
|
||||||
}
|
}
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
|
pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
|
||||||
|
@ -1894,7 +1892,6 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
|
||||||
if (!test_bit(STRIPE_R5C_CACHING, &sh->state) &&
|
if (!test_bit(STRIPE_R5C_CACHING, &sh->state) &&
|
||||||
test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags)) {
|
test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags)) {
|
||||||
r5l_recovery_replay_one_stripe(conf, sh, ctx);
|
r5l_recovery_replay_one_stripe(conf, sh, ctx);
|
||||||
sh->log_start = ctx->pos;
|
|
||||||
list_move_tail(&sh->lru, cached_stripe_list);
|
list_move_tail(&sh->lru, cached_stripe_list);
|
||||||
}
|
}
|
||||||
r5l_recovery_load_data(log, sh, ctx, payload,
|
r5l_recovery_load_data(log, sh, ctx, payload,
|
||||||
|
@ -1933,8 +1930,6 @@ static void r5c_recovery_load_one_stripe(struct r5l_log *log,
|
||||||
set_bit(R5_UPTODATE, &dev->flags);
|
set_bit(R5_UPTODATE, &dev->flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list_add_tail(&sh->r5c, &log->stripe_in_journal_list);
|
|
||||||
atomic_inc(&log->stripe_in_journal_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2070,6 +2065,7 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
|
||||||
struct stripe_head *sh, *next;
|
struct stripe_head *sh, *next;
|
||||||
struct mddev *mddev = log->rdev->mddev;
|
struct mddev *mddev = log->rdev->mddev;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
sector_t next_checkpoint = MaxSector;
|
||||||
|
|
||||||
page = alloc_page(GFP_KERNEL);
|
page = alloc_page(GFP_KERNEL);
|
||||||
if (!page) {
|
if (!page) {
|
||||||
|
@ -2078,6 +2074,8 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WARN_ON(list_empty(&ctx->cached_list));
|
||||||
|
|
||||||
list_for_each_entry_safe(sh, next, &ctx->cached_list, lru) {
|
list_for_each_entry_safe(sh, next, &ctx->cached_list, lru) {
|
||||||
struct r5l_meta_block *mb;
|
struct r5l_meta_block *mb;
|
||||||
int i;
|
int i;
|
||||||
|
@ -2123,12 +2121,15 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
|
||||||
sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page,
|
sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page,
|
||||||
REQ_OP_WRITE, REQ_FUA, false);
|
REQ_OP_WRITE, REQ_FUA, false);
|
||||||
sh->log_start = ctx->pos;
|
sh->log_start = ctx->pos;
|
||||||
|
list_add_tail(&sh->r5c, &log->stripe_in_journal_list);
|
||||||
|
atomic_inc(&log->stripe_in_journal_count);
|
||||||
ctx->pos = write_pos;
|
ctx->pos = write_pos;
|
||||||
ctx->seq += 1;
|
ctx->seq += 1;
|
||||||
|
next_checkpoint = sh->log_start;
|
||||||
list_del_init(&sh->lru);
|
list_del_init(&sh->lru);
|
||||||
raid5_release_stripe(sh);
|
raid5_release_stripe(sh);
|
||||||
}
|
}
|
||||||
|
log->next_checkpoint = next_checkpoint;
|
||||||
__free_page(page);
|
__free_page(page);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2139,7 +2140,6 @@ static int r5l_recovery_log(struct r5l_log *log)
|
||||||
struct r5l_recovery_ctx ctx;
|
struct r5l_recovery_ctx ctx;
|
||||||
int ret;
|
int ret;
|
||||||
sector_t pos;
|
sector_t pos;
|
||||||
struct stripe_head *sh;
|
|
||||||
|
|
||||||
ctx.pos = log->last_checkpoint;
|
ctx.pos = log->last_checkpoint;
|
||||||
ctx.seq = log->last_cp_seq;
|
ctx.seq = log->last_cp_seq;
|
||||||
|
@ -2164,16 +2164,13 @@ static int r5l_recovery_log(struct r5l_log *log)
|
||||||
log->next_checkpoint = ctx.pos;
|
log->next_checkpoint = ctx.pos;
|
||||||
r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq++);
|
r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq++);
|
||||||
ctx.pos = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
|
ctx.pos = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
|
||||||
} else {
|
|
||||||
sh = list_last_entry(&ctx.cached_list, struct stripe_head, lru);
|
|
||||||
log->next_checkpoint = sh->log_start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ctx.data_only_stripes == 0) && (ctx.data_parity_stripes == 0))
|
if ((ctx.data_only_stripes == 0) && (ctx.data_parity_stripes == 0))
|
||||||
pr_debug("md/raid:%s: starting from clean shutdown\n",
|
pr_debug("md/raid:%s: starting from clean shutdown\n",
|
||||||
mdname(mddev));
|
mdname(mddev));
|
||||||
else {
|
else {
|
||||||
pr_debug("md/raid:%s: recoverying %d data-only stripes and %d data-parity stripes\n",
|
pr_debug("md/raid:%s: recovering %d data-only stripes and %d data-parity stripes\n",
|
||||||
mdname(mddev), ctx.data_only_stripes,
|
mdname(mddev), ctx.data_only_stripes,
|
||||||
ctx.data_parity_stripes);
|
ctx.data_parity_stripes);
|
||||||
|
|
||||||
|
@ -2418,9 +2415,6 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
|
||||||
if (do_wakeup)
|
if (do_wakeup)
|
||||||
wake_up(&conf->wait_for_overlap);
|
wake_up(&conf->wait_for_overlap);
|
||||||
|
|
||||||
if (conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH)
|
|
||||||
return;
|
|
||||||
|
|
||||||
spin_lock_irq(&conf->log->stripe_in_journal_lock);
|
spin_lock_irq(&conf->log->stripe_in_journal_lock);
|
||||||
list_del_init(&sh->r5c);
|
list_del_init(&sh->r5c);
|
||||||
spin_unlock_irq(&conf->log->stripe_in_journal_lock);
|
spin_unlock_irq(&conf->log->stripe_in_journal_lock);
|
||||||
|
@ -2639,14 +2633,16 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
|
||||||
spin_lock_init(&log->stripe_in_journal_lock);
|
spin_lock_init(&log->stripe_in_journal_lock);
|
||||||
atomic_set(&log->stripe_in_journal_count, 0);
|
atomic_set(&log->stripe_in_journal_count, 0);
|
||||||
|
|
||||||
|
rcu_assign_pointer(conf->log, log);
|
||||||
|
|
||||||
if (r5l_load_log(log))
|
if (r5l_load_log(log))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
rcu_assign_pointer(conf->log, log);
|
|
||||||
set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
|
set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
rcu_assign_pointer(conf->log, NULL);
|
||||||
md_unregister_thread(&log->reclaim_thread);
|
md_unregister_thread(&log->reclaim_thread);
|
||||||
reclaim_thread:
|
reclaim_thread:
|
||||||
mempool_destroy(log->meta_pool);
|
mempool_destroy(log->meta_pool);
|
||||||
|
|
|
@ -62,6 +62,8 @@
|
||||||
#include "raid0.h"
|
#include "raid0.h"
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
|
||||||
|
#define UNSUPPORTED_MDDEV_FLAGS (1L << MD_FAILFAST_SUPPORTED)
|
||||||
|
|
||||||
#define cpu_to_group(cpu) cpu_to_node(cpu)
|
#define cpu_to_group(cpu) cpu_to_node(cpu)
|
||||||
#define ANY_GROUP NUMA_NO_NODE
|
#define ANY_GROUP NUMA_NO_NODE
|
||||||
|
|
||||||
|
@ -7829,8 +7831,9 @@ static void *raid5_takeover_raid1(struct mddev *mddev)
|
||||||
mddev->new_chunk_sectors = chunksect;
|
mddev->new_chunk_sectors = chunksect;
|
||||||
|
|
||||||
ret = setup_conf(mddev);
|
ret = setup_conf(mddev);
|
||||||
if (!IS_ERR_VALUE(ret))
|
if (!IS_ERR(ret))
|
||||||
clear_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
|
mddev_clear_unsupported_flags(mddev,
|
||||||
|
UNSUPPORTED_MDDEV_FLAGS);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,9 @@ static void mei_mkhi_fix(struct mei_cl_device *cldev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!cldev->bus->hbm_f_os_supported)
|
||||||
|
return;
|
||||||
|
|
||||||
ret = mei_cldev_enable(cldev);
|
ret = mei_cldev_enable(cldev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -180,6 +180,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf,
|
||||||
dev->hbm_f_ev_supported);
|
dev->hbm_f_ev_supported);
|
||||||
pos += scnprintf(buf + pos, bufsz - pos, "\tFA: %01d\n",
|
pos += scnprintf(buf + pos, bufsz - pos, "\tFA: %01d\n",
|
||||||
dev->hbm_f_fa_supported);
|
dev->hbm_f_fa_supported);
|
||||||
|
pos += scnprintf(buf + pos, bufsz - pos, "\tOS: %01d\n",
|
||||||
|
dev->hbm_f_os_supported);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += scnprintf(buf + pos, bufsz - pos, "pg: %s, %s\n",
|
pos += scnprintf(buf + pos, bufsz - pos, "pg: %s, %s\n",
|
||||||
|
|
|
@ -989,6 +989,10 @@ static void mei_hbm_config_features(struct mei_device *dev)
|
||||||
/* Fixed Address Client Support */
|
/* Fixed Address Client Support */
|
||||||
if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
|
if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
|
||||||
dev->hbm_f_fa_supported = 1;
|
dev->hbm_f_fa_supported = 1;
|
||||||
|
|
||||||
|
/* OS ver message Support */
|
||||||
|
if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
|
||||||
|
dev->hbm_f_os_supported = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -76,6 +76,12 @@
|
||||||
#define HBM_MINOR_VERSION_FA 0
|
#define HBM_MINOR_VERSION_FA 0
|
||||||
#define HBM_MAJOR_VERSION_FA 2
|
#define HBM_MAJOR_VERSION_FA 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MEI version with OS ver message support
|
||||||
|
*/
|
||||||
|
#define HBM_MINOR_VERSION_OS 0
|
||||||
|
#define HBM_MAJOR_VERSION_OS 2
|
||||||
|
|
||||||
/* Host bus message command opcode */
|
/* Host bus message command opcode */
|
||||||
#define MEI_HBM_CMD_OP_MSK 0x7f
|
#define MEI_HBM_CMD_OP_MSK 0x7f
|
||||||
/* Host bus message command RESPONSE */
|
/* Host bus message command RESPONSE */
|
||||||
|
|
|
@ -406,6 +406,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
|
||||||
* @hbm_f_ev_supported : hbm feature event notification
|
* @hbm_f_ev_supported : hbm feature event notification
|
||||||
* @hbm_f_fa_supported : hbm feature fixed address client
|
* @hbm_f_fa_supported : hbm feature fixed address client
|
||||||
* @hbm_f_ie_supported : hbm feature immediate reply to enum request
|
* @hbm_f_ie_supported : hbm feature immediate reply to enum request
|
||||||
|
* @hbm_f_os_supported : hbm feature support OS ver message
|
||||||
*
|
*
|
||||||
* @me_clients_rwsem: rw lock over me_clients list
|
* @me_clients_rwsem: rw lock over me_clients list
|
||||||
* @me_clients : list of FW clients
|
* @me_clients : list of FW clients
|
||||||
|
@ -487,6 +488,7 @@ struct mei_device {
|
||||||
unsigned int hbm_f_ev_supported:1;
|
unsigned int hbm_f_ev_supported:1;
|
||||||
unsigned int hbm_f_fa_supported:1;
|
unsigned int hbm_f_fa_supported:1;
|
||||||
unsigned int hbm_f_ie_supported:1;
|
unsigned int hbm_f_ie_supported:1;
|
||||||
|
unsigned int hbm_f_os_supported:1;
|
||||||
|
|
||||||
struct rw_semaphore me_clients_rwsem;
|
struct rw_semaphore me_clients_rwsem;
|
||||||
struct list_head me_clients;
|
struct list_head me_clients;
|
||||||
|
|
|
@ -506,9 +506,6 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||||
}
|
}
|
||||||
} while (busy);
|
} while (busy);
|
||||||
|
|
||||||
if (host->ops->card_busy && send_status)
|
|
||||||
return mmc_switch_status(card);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,24 +574,26 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||||
if (!use_busy_signal)
|
if (!use_busy_signal)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Switch to new timing before poll and check switch status. */
|
|
||||||
if (timing)
|
|
||||||
mmc_set_timing(host, timing);
|
|
||||||
|
|
||||||
/*If SPI or used HW busy detection above, then we don't need to poll. */
|
/*If SPI or used HW busy detection above, then we don't need to poll. */
|
||||||
if (((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ||
|
if (((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ||
|
||||||
mmc_host_is_spi(host)) {
|
mmc_host_is_spi(host))
|
||||||
if (send_status)
|
|
||||||
err = mmc_switch_status(card);
|
|
||||||
goto out_tim;
|
goto out_tim;
|
||||||
}
|
|
||||||
|
|
||||||
/* Let's try to poll to find out when the command is completed. */
|
/* Let's try to poll to find out when the command is completed. */
|
||||||
err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err);
|
err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
out_tim:
|
out_tim:
|
||||||
if (err && timing)
|
/* Switch to new timing before check switch status. */
|
||||||
mmc_set_timing(host, old_timing);
|
if (timing)
|
||||||
|
mmc_set_timing(host, timing);
|
||||||
|
|
||||||
|
if (send_status) {
|
||||||
|
err = mmc_switch_status(card);
|
||||||
|
if (err && timing)
|
||||||
|
mmc_set_timing(host, old_timing);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
mmc_retune_release(host);
|
mmc_retune_release(host);
|
||||||
|
|
||||||
|
|
|
@ -578,13 +578,15 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct meson_host *host = dev_id;
|
struct meson_host *host = dev_id;
|
||||||
struct mmc_request *mrq;
|
struct mmc_request *mrq;
|
||||||
struct mmc_command *cmd = host->cmd;
|
struct mmc_command *cmd;
|
||||||
u32 irq_en, status, raw_status;
|
u32 irq_en, status, raw_status;
|
||||||
irqreturn_t ret = IRQ_HANDLED;
|
irqreturn_t ret = IRQ_HANDLED;
|
||||||
|
|
||||||
if (WARN_ON(!host))
|
if (WARN_ON(!host))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
cmd = host->cmd;
|
||||||
|
|
||||||
mrq = host->mrq;
|
mrq = host->mrq;
|
||||||
|
|
||||||
if (WARN_ON(!mrq))
|
if (WARN_ON(!mrq))
|
||||||
|
@ -670,10 +672,10 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
|
||||||
int ret = IRQ_HANDLED;
|
int ret = IRQ_HANDLED;
|
||||||
|
|
||||||
if (WARN_ON(!mrq))
|
if (WARN_ON(!mrq))
|
||||||
ret = IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
if (WARN_ON(!cmd))
|
if (WARN_ON(!cmd))
|
||||||
ret = IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
data = cmd->data;
|
data = cmd->data;
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
|
@ -309,6 +309,9 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
|
||||||
cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
|
cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
|
||||||
cmd1 = cmd->arg;
|
cmd1 = cmd->arg;
|
||||||
|
|
||||||
|
if (cmd->opcode == MMC_STOP_TRANSMISSION)
|
||||||
|
cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
|
||||||
|
|
||||||
if (host->sdio_irq_en) {
|
if (host->sdio_irq_en) {
|
||||||
ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
|
ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
|
||||||
cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
|
cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
|
||||||
|
@ -417,8 +420,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
|
||||||
ssp->base + HW_SSP_BLOCK_SIZE);
|
ssp->base + HW_SSP_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
|
if (cmd->opcode == SD_IO_RW_EXTENDED)
|
||||||
(cmd->opcode == SD_IO_RW_EXTENDED))
|
|
||||||
cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
|
cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
|
||||||
|
|
||||||
cmd1 = cmd->arg;
|
cmd1 = cmd->arg;
|
||||||
|
|
|
@ -395,7 +395,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
||||||
/* Power on the SDHCI controller and its children */
|
/* Power on the SDHCI controller and its children */
|
||||||
acpi_device_fix_up_power(device);
|
acpi_device_fix_up_power(device);
|
||||||
list_for_each_entry(child, &device->children, node)
|
list_for_each_entry(child, &device->children, node)
|
||||||
acpi_device_fix_up_power(child);
|
if (child->status.present && child->status.enabled)
|
||||||
|
acpi_device_fix_up_power(child);
|
||||||
|
|
||||||
if (acpi_bus_get_status(device) || !device->status.present)
|
if (acpi_bus_get_status(device) || !device->status.present)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
|
@ -426,6 +426,7 @@ config MTD_NAND_ORION
|
||||||
|
|
||||||
config MTD_NAND_OXNAS
|
config MTD_NAND_OXNAS
|
||||||
tristate "NAND Flash support for Oxford Semiconductor SoC"
|
tristate "NAND Flash support for Oxford Semiconductor SoC"
|
||||||
|
depends on HAS_IOMEM
|
||||||
help
|
help
|
||||||
This enables the NAND flash controller on Oxford Semiconductor SoCs.
|
This enables the NAND flash controller on Oxford Semiconductor SoCs.
|
||||||
|
|
||||||
|
@ -540,7 +541,7 @@ config MTD_NAND_FSMC
|
||||||
Flexible Static Memory Controller (FSMC)
|
Flexible Static Memory Controller (FSMC)
|
||||||
|
|
||||||
config MTD_NAND_XWAY
|
config MTD_NAND_XWAY
|
||||||
tristate "Support for NAND on Lantiq XWAY SoC"
|
bool "Support for NAND on Lantiq XWAY SoC"
|
||||||
depends on LANTIQ && SOC_TYPE_XWAY
|
depends on LANTIQ && SOC_TYPE_XWAY
|
||||||
help
|
help
|
||||||
Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
|
Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
|
||||||
|
|
|
@ -775,7 +775,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
||||||
init_completion(&host->comp_controller);
|
init_completion(&host->comp_controller);
|
||||||
|
|
||||||
host->irq = platform_get_irq(pdev, 0);
|
host->irq = platform_get_irq(pdev, 0);
|
||||||
if ((host->irq < 0) || (host->irq >= NR_IRQS)) {
|
if (host->irq < 0) {
|
||||||
dev_err(&pdev->dev, "failed to get platform irq\n");
|
dev_err(&pdev->dev, "failed to get platform irq\n");
|
||||||
res = -EINVAL;
|
res = -EINVAL;
|
||||||
goto err_exit3;
|
goto err_exit3;
|
||||||
|
|
|
@ -632,11 +632,13 @@ static int tango_nand_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(nfc->pbus_base))
|
if (IS_ERR(nfc->pbus_base))
|
||||||
return PTR_ERR(nfc->pbus_base);
|
return PTR_ERR(nfc->pbus_base);
|
||||||
|
|
||||||
|
writel_relaxed(MODE_RAW, nfc->pbus_base + PBUS_PAD_MODE);
|
||||||
|
|
||||||
clk = clk_get(&pdev->dev, NULL);
|
clk = clk_get(&pdev->dev, NULL);
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
return PTR_ERR(clk);
|
return PTR_ERR(clk);
|
||||||
|
|
||||||
nfc->chan = dma_request_chan(&pdev->dev, "nfc_sbox");
|
nfc->chan = dma_request_chan(&pdev->dev, "rxtx");
|
||||||
if (IS_ERR(nfc->chan))
|
if (IS_ERR(nfc->chan))
|
||||||
return PTR_ERR(nfc->chan);
|
return PTR_ERR(nfc->chan);
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,6 @@ static const struct of_device_id xway_nand_match[] = {
|
||||||
{ .compatible = "lantiq,nand-xway" },
|
{ .compatible = "lantiq,nand-xway" },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, xway_nand_match);
|
|
||||||
|
|
||||||
static struct platform_driver xway_nand_driver = {
|
static struct platform_driver xway_nand_driver = {
|
||||||
.probe = xway_nand_probe,
|
.probe = xway_nand_probe,
|
||||||
|
@ -243,6 +242,4 @@ static struct platform_driver xway_nand_driver = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(xway_nand_driver);
|
builtin_platform_driver(xway_nand_driver);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
|
@ -710,11 +710,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||||
unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
|
unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
|
||||||
unsigned int pkts_compl = 0, bytes_compl = 0;
|
unsigned int pkts_compl = 0, bytes_compl = 0;
|
||||||
struct bcm_sysport_cb *cb;
|
struct bcm_sysport_cb *cb;
|
||||||
struct netdev_queue *txq;
|
|
||||||
u32 hw_ind;
|
u32 hw_ind;
|
||||||
|
|
||||||
txq = netdev_get_tx_queue(ndev, ring->index);
|
|
||||||
|
|
||||||
/* Compute how many descriptors have been processed since last call */
|
/* Compute how many descriptors have been processed since last call */
|
||||||
hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index));
|
hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index));
|
||||||
c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK;
|
c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK;
|
||||||
|
@ -745,9 +742,6 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||||
|
|
||||||
ring->c_index = c_index;
|
ring->c_index = c_index;
|
||||||
|
|
||||||
if (netif_tx_queue_stopped(txq) && pkts_compl)
|
|
||||||
netif_tx_wake_queue(txq);
|
|
||||||
|
|
||||||
netif_dbg(priv, tx_done, ndev,
|
netif_dbg(priv, tx_done, ndev,
|
||||||
"ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
|
"ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
|
||||||
ring->index, ring->c_index, pkts_compl, bytes_compl);
|
ring->index, ring->c_index, pkts_compl, bytes_compl);
|
||||||
|
@ -759,16 +753,33 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||||
static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||||
struct bcm_sysport_tx_ring *ring)
|
struct bcm_sysport_tx_ring *ring)
|
||||||
{
|
{
|
||||||
|
struct netdev_queue *txq;
|
||||||
unsigned int released;
|
unsigned int released;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
txq = netdev_get_tx_queue(priv->netdev, ring->index);
|
||||||
|
|
||||||
spin_lock_irqsave(&ring->lock, flags);
|
spin_lock_irqsave(&ring->lock, flags);
|
||||||
released = __bcm_sysport_tx_reclaim(priv, ring);
|
released = __bcm_sysport_tx_reclaim(priv, ring);
|
||||||
|
if (released)
|
||||||
|
netif_tx_wake_queue(txq);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ring->lock, flags);
|
spin_unlock_irqrestore(&ring->lock, flags);
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Locked version of the per-ring TX reclaim, but does not wake the queue */
|
||||||
|
static void bcm_sysport_tx_clean(struct bcm_sysport_priv *priv,
|
||||||
|
struct bcm_sysport_tx_ring *ring)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ring->lock, flags);
|
||||||
|
__bcm_sysport_tx_reclaim(priv, ring);
|
||||||
|
spin_unlock_irqrestore(&ring->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
|
static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
|
||||||
{
|
{
|
||||||
struct bcm_sysport_tx_ring *ring =
|
struct bcm_sysport_tx_ring *ring =
|
||||||
|
@ -1252,7 +1263,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
|
||||||
napi_disable(&ring->napi);
|
napi_disable(&ring->napi);
|
||||||
netif_napi_del(&ring->napi);
|
netif_napi_del(&ring->napi);
|
||||||
|
|
||||||
bcm_sysport_tx_reclaim(priv, ring);
|
bcm_sysport_tx_clean(priv, ring);
|
||||||
|
|
||||||
kfree(ring->cbs);
|
kfree(ring->cbs);
|
||||||
ring->cbs = NULL;
|
ring->cbs = NULL;
|
||||||
|
|
|
@ -47,8 +47,9 @@ struct lmac {
|
||||||
struct bgx {
|
struct bgx {
|
||||||
u8 bgx_id;
|
u8 bgx_id;
|
||||||
struct lmac lmac[MAX_LMAC_PER_BGX];
|
struct lmac lmac[MAX_LMAC_PER_BGX];
|
||||||
int lmac_count;
|
u8 lmac_count;
|
||||||
u8 max_lmac;
|
u8 max_lmac;
|
||||||
|
u8 acpi_lmac_idx;
|
||||||
void __iomem *reg_base;
|
void __iomem *reg_base;
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
bool is_dlm;
|
bool is_dlm;
|
||||||
|
@ -1143,13 +1144,13 @@ static acpi_status bgx_acpi_register_phy(acpi_handle handle,
|
||||||
if (acpi_bus_get_device(handle, &adev))
|
if (acpi_bus_get_device(handle, &adev))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
acpi_get_mac_address(dev, adev, bgx->lmac[bgx->lmac_count].mac);
|
acpi_get_mac_address(dev, adev, bgx->lmac[bgx->acpi_lmac_idx].mac);
|
||||||
|
|
||||||
SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, dev);
|
SET_NETDEV_DEV(&bgx->lmac[bgx->acpi_lmac_idx].netdev, dev);
|
||||||
|
|
||||||
bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count;
|
bgx->lmac[bgx->acpi_lmac_idx].lmacid = bgx->acpi_lmac_idx;
|
||||||
|
bgx->acpi_lmac_idx++; /* move to next LMAC */
|
||||||
out:
|
out:
|
||||||
bgx->lmac_count++;
|
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1118,7 +1118,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
|
||||||
err:
|
err:
|
||||||
mutex_unlock(&adapter->mcc_lock);
|
mutex_unlock(&adapter->mcc_lock);
|
||||||
|
|
||||||
if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
|
if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
|
||||||
status = -EPERM;
|
status = -EPERM;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue