Linux 4.4-rc4

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJWZMgaAAoJEHm+PkMAQRiGGcIH+gNS/hbN2DKW7wphl1QuaV7C
 1fror8AvpwbGa/o0yuxovaVuZzAR0TF31vn+gAemF4U/hnM25xqxEHXYZEVv8OWw
 mbz4/z+jbVk3SiS5AiZPIZgL4W6RZnG5QYfiTVGPlBHuBznW2ITlNlClBOmBL45o
 uhb3bjTzi70AZ7Gh6i9sHgJoHg6D9u/ZxLaLcWnM79BzyTMHTf2t0wnrQmh66lEE
 hp7Rn9wXv9bk/e3iH7CVUb97P4IWhhkmfqcoturqAg9+C/M26b0VmvQp9Sy8S6Pd
 FVQ+SUIZllj5ZDKe9mOcs37czlxTr0keEFqzWeMh/7y4iuI3RaRp/qb+7mX5sIE=
 =WGZ1
 -----END PGP SIGNATURE-----

Back merge tag 'v4.4-rc4' into drm-next

We've picked up a few conflicts and it would be nice
to resolve them before we move onwards.
This commit is contained in:
Dave Airlie 2015-12-08 11:04:26 +10:00
commit e876b41ab0
357 changed files with 4890 additions and 1603 deletions

View File

@ -8,6 +8,11 @@ Required properties:
- phy-mode: See ethernet.txt file in the same directory
- clocks: a pointer to the reference clock for this device.
Optional properties:
- tx-csum-limit: maximum mtu supported by port that allow TX checksum.
Value is presented in bytes. If not used, by default 1600B is set for
"marvell,armada-370-neta" and 9800B for others.
Example:
ethernet@d0070000 {
@ -15,6 +20,7 @@ ethernet@d0070000 {
reg = <0xd0070000 0x2500>;
interrupts = <8>;
clocks = <&gate_clk 4>;
tx-csum-limit = <9800>
status = "okay";
phy = <&phy0>;
phy-mode = "rgmii-id";

View File

@ -318,7 +318,7 @@ M: Zhang Rui <rui.zhang@intel.com>
L: linux-acpi@vger.kernel.org
W: https://01.org/linux-acpi
S: Supported
F: drivers/acpi/video.c
F: drivers/acpi/acpi_video.c
ACPI WMI DRIVER
L: platform-driver-x86@vger.kernel.org
@ -1847,7 +1847,7 @@ S: Supported
F: drivers/net/wireless/ath/ath6kl/
WILOCITY WIL6210 WIRELESS DRIVER
M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
M: Maya Erez <qca_merez@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
L: wil6210@qca.qualcomm.com
S: Supported
@ -9427,8 +9427,10 @@ F: include/scsi/sg.h
SCSI SUBSYSTEM
M: "James E.J. Bottomley" <JBottomley@odin.com>
L: linux-scsi@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
M: "Martin K. Petersen" <martin.petersen@oracle.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/
F: include/scsi/
@ -10903,9 +10905,9 @@ S: Maintained
F: drivers/media/tuners/tua9001*
TULIP NETWORK DRIVERS
M: Grant Grundler <grundler@parisc-linux.org>
L: netdev@vger.kernel.org
S: Maintained
L: linux-parisc@vger.kernel.org
S: Orphan
F: drivers/net/ethernet/dec/tulip/
TUN/TAP driver

View File

@ -1,7 +1,7 @@
VERSION = 4
PATCHLEVEL = 4
SUBLEVEL = 0
EXTRAVERSION = -rc3
EXTRAVERSION = -rc4
NAME = Blurry Fish Butt
# *DOCUMENTATION*

View File

@ -498,6 +498,7 @@
reg = <0x70000 0x4000>;
interrupts-extended = <&mpic 8>;
clocks = <&gateclk 4>;
tx-csum-limit = <9800>;
status = "disabled";
};

View File

@ -28,6 +28,18 @@
unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu);
static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu,
u8 reg_num)
{
return *vcpu_reg(vcpu, reg_num);
}
static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
unsigned long val)
{
*vcpu_reg(vcpu, reg_num) = val;
}
bool kvm_condition_valid(struct kvm_vcpu *vcpu);
void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr);
void kvm_inject_undefined(struct kvm_vcpu *vcpu);

View File

@ -115,7 +115,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
data);
data = vcpu_data_host_to_guest(vcpu, data, len);
*vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt) = data;
vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data);
}
return 0;
@ -186,7 +186,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
rt = vcpu->arch.mmio_decode.rt;
if (is_write) {
data = vcpu_data_guest_to_host(vcpu, *vcpu_reg(vcpu, rt), len);
data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt),
len);
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
mmio_write_buf(data_buf, len, data);

View File

@ -218,7 +218,7 @@ static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
kvm_tlb_flush_vmid_ipa(kvm, addr);
/* No need to invalidate the cache for device mappings */
if (!kvm_is_device_pfn(__phys_to_pfn(addr)))
if (!kvm_is_device_pfn(pte_pfn(old_pte)))
kvm_flush_dcache_pte(old_pte);
put_page(virt_to_page(pte));
@ -310,7 +310,7 @@ static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
pte = pte_offset_kernel(pmd, addr);
do {
if (!pte_none(*pte) && !kvm_is_device_pfn(__phys_to_pfn(addr)))
if (!pte_none(*pte) && !kvm_is_device_pfn(pte_pfn(*pte)))
kvm_flush_dcache_pte(*pte);
} while (pte++, addr += PAGE_SIZE, addr != end);
}

View File

@ -75,7 +75,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
unsigned long context_id;
phys_addr_t target_pc;
cpu_id = *vcpu_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
if (vcpu_mode_is_32bit(source_vcpu))
cpu_id &= ~((u32) 0);
@ -94,8 +94,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
return PSCI_RET_INVALID_PARAMS;
}
target_pc = *vcpu_reg(source_vcpu, 2);
context_id = *vcpu_reg(source_vcpu, 3);
target_pc = vcpu_get_reg(source_vcpu, 2);
context_id = vcpu_get_reg(source_vcpu, 3);
kvm_reset_vcpu(vcpu);
@ -114,7 +114,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
* NOTE: We always update r0 (or x0) because for PSCI v0.1
* the general puspose registers are undefined upon CPU_ON.
*/
*vcpu_reg(vcpu, 0) = context_id;
vcpu_set_reg(vcpu, 0, context_id);
vcpu->arch.power_off = false;
smp_mb(); /* Make sure the above is visible */
@ -134,8 +134,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
struct kvm *kvm = vcpu->kvm;
struct kvm_vcpu *tmp;
target_affinity = *vcpu_reg(vcpu, 1);
lowest_affinity_level = *vcpu_reg(vcpu, 2);
target_affinity = vcpu_get_reg(vcpu, 1);
lowest_affinity_level = vcpu_get_reg(vcpu, 2);
/* Determine target affinity mask */
target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
@ -209,7 +209,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
{
int ret = 1;
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
@ -273,13 +273,13 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
break;
}
*vcpu_reg(vcpu, 0) = val;
vcpu_set_reg(vcpu, 0, val);
return ret;
}
static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
{
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
switch (psci_fn) {
@ -295,7 +295,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
break;
}
*vcpu_reg(vcpu, 0) = val;
vcpu_set_reg(vcpu, 0, val);
return 1;
}

View File

@ -100,13 +100,21 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
}
/*
* vcpu_reg should always be passed a register number coming from a
* read of ESR_EL2. Otherwise, it may give the wrong result on AArch32
* with banked registers.
* vcpu_get_reg and vcpu_set_reg should always be passed a register number
* coming from a read of ESR_EL2. Otherwise, it may give the wrong result on
* AArch32 with banked registers.
*/
static inline unsigned long *vcpu_reg(const struct kvm_vcpu *vcpu, u8 reg_num)
static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
u8 reg_num)
{
return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.regs[reg_num];
return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs.regs[reg_num];
}
static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
unsigned long val)
{
if (reg_num != 31)
vcpu_gp_regs(vcpu)->regs.regs[reg_num] = val;
}
/* Get vcpu SPSR for current mode */

View File

@ -37,7 +37,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
int ret;
trace_kvm_hvc_arm64(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
trace_kvm_hvc_arm64(*vcpu_pc(vcpu), vcpu_get_reg(vcpu, 0),
kvm_vcpu_hvc_get_imm(vcpu));
ret = kvm_psci_call(vcpu);

View File

@ -78,7 +78,7 @@ static u32 get_ccsidr(u32 csselr)
* See note at ARMv7 ARM B1.14.4 (TL;DR: S/W ops are not easily virtualized).
*/
static bool access_dcsw(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (!p->is_write)
@ -94,21 +94,19 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
* sys_regs and leave it in complete control of the caches.
*/
static bool access_vm_reg(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
unsigned long val;
bool was_enabled = vcpu_has_cache_enabled(vcpu);
BUG_ON(!p->is_write);
val = *vcpu_reg(vcpu, p->Rt);
if (!p->is_aarch32) {
vcpu_sys_reg(vcpu, r->reg) = val;
vcpu_sys_reg(vcpu, r->reg) = p->regval;
} else {
if (!p->is_32bit)
vcpu_cp15_64_high(vcpu, r->reg) = val >> 32;
vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL;
vcpu_cp15_64_high(vcpu, r->reg) = upper_32_bits(p->regval);
vcpu_cp15_64_low(vcpu, r->reg) = lower_32_bits(p->regval);
}
kvm_toggle_cache(vcpu, was_enabled);
@ -122,22 +120,19 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
* for both AArch64 and AArch32 accesses.
*/
static bool access_gic_sgi(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
u64 val;
if (!p->is_write)
return read_from_write_only(vcpu, p);
val = *vcpu_reg(vcpu, p->Rt);
vgic_v3_dispatch_sgi(vcpu, val);
vgic_v3_dispatch_sgi(vcpu, p->regval);
return true;
}
static bool trap_raz_wi(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (p->is_write)
@ -147,19 +142,19 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
}
static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (p->is_write) {
return ignore_write(vcpu, p);
} else {
*vcpu_reg(vcpu, p->Rt) = (1 << 3);
p->regval = (1 << 3);
return true;
}
}
static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (p->is_write) {
@ -167,7 +162,7 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
} else {
u32 val;
asm volatile("mrs %0, dbgauthstatus_el1" : "=r" (val));
*vcpu_reg(vcpu, p->Rt) = val;
p->regval = val;
return true;
}
}
@ -200,17 +195,17 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
* now use the debug registers.
*/
static bool trap_debug_regs(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (p->is_write) {
vcpu_sys_reg(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
vcpu_sys_reg(vcpu, r->reg) = p->regval;
vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
} else {
*vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, r->reg);
p->regval = vcpu_sys_reg(vcpu, r->reg);
}
trace_trap_reg(__func__, r->reg, p->is_write, *vcpu_reg(vcpu, p->Rt));
trace_trap_reg(__func__, r->reg, p->is_write, p->regval);
return true;
}
@ -225,10 +220,10 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
* hyp.S code switches between host and guest values in future.
*/
static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
u64 *dbg_reg)
{
u64 val = *vcpu_reg(vcpu, p->Rt);
u64 val = p->regval;
if (p->is_32bit) {
val &= 0xffffffffUL;
@ -240,19 +235,16 @@ static inline void reg_to_dbg(struct kvm_vcpu *vcpu,
}
static inline void dbg_to_reg(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
u64 *dbg_reg)
{
u64 val = *dbg_reg;
p->regval = *dbg_reg;
if (p->is_32bit)
val &= 0xffffffffUL;
*vcpu_reg(vcpu, p->Rt) = val;
p->regval &= 0xffffffffUL;
}
static inline bool trap_bvr(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *rd)
{
u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
@ -294,7 +286,7 @@ static inline void reset_bvr(struct kvm_vcpu *vcpu,
}
static inline bool trap_bcr(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *rd)
{
u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
@ -337,7 +329,7 @@ static inline void reset_bcr(struct kvm_vcpu *vcpu,
}
static inline bool trap_wvr(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *rd)
{
u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
@ -380,7 +372,7 @@ static inline void reset_wvr(struct kvm_vcpu *vcpu,
}
static inline bool trap_wcr(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *rd)
{
u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
@ -687,7 +679,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
};
static bool trap_dbgidr(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (p->is_write) {
@ -697,23 +689,23 @@ static bool trap_dbgidr(struct kvm_vcpu *vcpu,
u64 pfr = read_system_reg(SYS_ID_AA64PFR0_EL1);
u32 el3 = !!cpuid_feature_extract_field(pfr, ID_AA64PFR0_EL3_SHIFT);
*vcpu_reg(vcpu, p->Rt) = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) |
(((dfr >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) << 24) |
(((dfr >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) << 20) |
(6 << 16) | (el3 << 14) | (el3 << 12));
p->regval = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) |
(((dfr >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) << 24) |
(((dfr >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) << 20)
| (6 << 16) | (el3 << 14) | (el3 << 12));
return true;
}
}
static bool trap_debug32(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (p->is_write) {
vcpu_cp14(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
vcpu_cp14(vcpu, r->reg) = p->regval;
vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
} else {
*vcpu_reg(vcpu, p->Rt) = vcpu_cp14(vcpu, r->reg);
p->regval = vcpu_cp14(vcpu, r->reg);
}
return true;
@ -731,7 +723,7 @@ static bool trap_debug32(struct kvm_vcpu *vcpu,
*/
static inline bool trap_xvr(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *rd)
{
u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
@ -740,12 +732,12 @@ static inline bool trap_xvr(struct kvm_vcpu *vcpu,
u64 val = *dbg_reg;
val &= 0xffffffffUL;
val |= *vcpu_reg(vcpu, p->Rt) << 32;
val |= p->regval << 32;
*dbg_reg = val;
vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
} else {
*vcpu_reg(vcpu, p->Rt) = *dbg_reg >> 32;
p->regval = *dbg_reg >> 32;
}
trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
@ -991,7 +983,7 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
* Return 0 if the access has been handled, and -1 if not.
*/
static int emulate_cp(struct kvm_vcpu *vcpu,
const struct sys_reg_params *params,
struct sys_reg_params *params,
const struct sys_reg_desc *table,
size_t num)
{
@ -1062,12 +1054,12 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
{
struct sys_reg_params params;
u32 hsr = kvm_vcpu_get_hsr(vcpu);
int Rt = (hsr >> 5) & 0xf;
int Rt2 = (hsr >> 10) & 0xf;
params.is_aarch32 = true;
params.is_32bit = false;
params.CRm = (hsr >> 1) & 0xf;
params.Rt = (hsr >> 5) & 0xf;
params.is_write = ((hsr & 1) == 0);
params.Op0 = 0;
@ -1076,15 +1068,12 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
params.CRn = 0;
/*
* Massive hack here. Store Rt2 in the top 32bits so we only
* have one register to deal with. As we use the same trap
* Make a 64-bit value out of Rt and Rt2. As we use the same trap
* backends between AArch32 and AArch64, we get away with it.
*/
if (params.is_write) {
u64 val = *vcpu_reg(vcpu, params.Rt);
val &= 0xffffffff;
val |= *vcpu_reg(vcpu, Rt2) << 32;
*vcpu_reg(vcpu, params.Rt) = val;
params.regval = vcpu_get_reg(vcpu, Rt) & 0xffffffff;
params.regval |= vcpu_get_reg(vcpu, Rt2) << 32;
}
if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
@ -1095,11 +1084,10 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
unhandled_cp_access(vcpu, &params);
out:
/* Do the opposite hack for the read side */
/* Split up the value between registers for the read side */
if (!params.is_write) {
u64 val = *vcpu_reg(vcpu, params.Rt);
val >>= 32;
*vcpu_reg(vcpu, Rt2) = val;
vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval));
vcpu_set_reg(vcpu, Rt2, upper_32_bits(params.regval));
}
return 1;
@ -1118,21 +1106,24 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
{
struct sys_reg_params params;
u32 hsr = kvm_vcpu_get_hsr(vcpu);
int Rt = (hsr >> 5) & 0xf;
params.is_aarch32 = true;
params.is_32bit = true;
params.CRm = (hsr >> 1) & 0xf;
params.Rt = (hsr >> 5) & 0xf;
params.regval = vcpu_get_reg(vcpu, Rt);
params.is_write = ((hsr & 1) == 0);
params.CRn = (hsr >> 10) & 0xf;
params.Op0 = 0;
params.Op1 = (hsr >> 14) & 0x7;
params.Op2 = (hsr >> 17) & 0x7;
if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
return 1;
if (!emulate_cp(vcpu, &params, global, nr_global))
if (!emulate_cp(vcpu, &params, target_specific, nr_specific) ||
!emulate_cp(vcpu, &params, global, nr_global)) {
if (!params.is_write)
vcpu_set_reg(vcpu, Rt, params.regval);
return 1;
}
unhandled_cp_access(vcpu, &params);
return 1;
@ -1175,7 +1166,7 @@ int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
}
static int emulate_sys_reg(struct kvm_vcpu *vcpu,
const struct sys_reg_params *params)
struct sys_reg_params *params)
{
size_t num;
const struct sys_reg_desc *table, *r;
@ -1230,6 +1221,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
struct sys_reg_params params;
unsigned long esr = kvm_vcpu_get_hsr(vcpu);
int Rt = (esr >> 5) & 0x1f;
int ret;
trace_kvm_handle_sys_reg(esr);
@ -1240,10 +1233,14 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
params.CRn = (esr >> 10) & 0xf;
params.CRm = (esr >> 1) & 0xf;
params.Op2 = (esr >> 17) & 0x7;
params.Rt = (esr >> 5) & 0x1f;
params.regval = vcpu_get_reg(vcpu, Rt);
params.is_write = !(esr & 1);
return emulate_sys_reg(vcpu, &params);
ret = emulate_sys_reg(vcpu, &params);
if (!params.is_write)
vcpu_set_reg(vcpu, Rt, params.regval);
return ret;
}
/******************************************************************************

View File

@ -28,7 +28,7 @@ struct sys_reg_params {
u8 CRn;
u8 CRm;
u8 Op2;
u8 Rt;
u64 regval;
bool is_write;
bool is_aarch32;
bool is_32bit; /* Only valid if is_aarch32 is true */
@ -44,7 +44,7 @@ struct sys_reg_desc {
/* Trapped access from guest, if non-NULL. */
bool (*access)(struct kvm_vcpu *,
const struct sys_reg_params *,
struct sys_reg_params *,
const struct sys_reg_desc *);
/* Initialization for vcpu. */
@ -77,9 +77,9 @@ static inline bool ignore_write(struct kvm_vcpu *vcpu,
}
static inline bool read_zero(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p)
struct sys_reg_params *p)
{
*vcpu_reg(vcpu, p->Rt) = 0;
p->regval = 0;
return true;
}

View File

@ -31,13 +31,13 @@
#include "sys_regs.h"
static bool access_actlr(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
if (p->is_write)
return ignore_write(vcpu, p);
*vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, ACTLR_EL1);
p->regval = vcpu_sys_reg(vcpu, ACTLR_EL1);
return true;
}

View File

@ -139,6 +139,12 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
/* Stack must be multiples of 16B */
#define STACK_ALIGN(sz) (((sz) + 15) & ~15)
#define _STACK_SIZE \
(MAX_BPF_STACK \
+ 4 /* extra for skb_copy_bits buffer */)
#define STACK_SIZE STACK_ALIGN(_STACK_SIZE)
static void build_prologue(struct jit_ctx *ctx)
{
const u8 r6 = bpf2a64[BPF_REG_6];
@ -150,10 +156,6 @@ static void build_prologue(struct jit_ctx *ctx)
const u8 rx = bpf2a64[BPF_REG_X];
const u8 tmp1 = bpf2a64[TMP_REG_1];
const u8 tmp2 = bpf2a64[TMP_REG_2];
int stack_size = MAX_BPF_STACK;
stack_size += 4; /* extra for skb_copy_bits buffer */
stack_size = STACK_ALIGN(stack_size);
/*
* BPF prog stack layout
@ -165,12 +167,13 @@ static void build_prologue(struct jit_ctx *ctx)
* | ... | callee saved registers
* +-----+
* | | x25/x26
* BPF fp register => -80:+-----+
* BPF fp register => -80:+-----+ <= (BPF_FP)
* | |
* | ... | BPF prog stack
* | |
* | |
* current A64_SP => +-----+
* +-----+ <= (BPF_FP - MAX_BPF_STACK)
* |RSVD | JIT scratchpad
* current A64_SP => +-----+ <= (BPF_FP - STACK_SIZE)
* | |
* | ... | Function call stack
* | |
@ -196,7 +199,7 @@ static void build_prologue(struct jit_ctx *ctx)
emit(A64_MOV(1, fp, A64_SP), ctx);
/* Set up function call stack */
emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx);
emit(A64_SUB_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
/* Clear registers A and X */
emit_a64_mov_i64(ra, 0, ctx);
@ -213,13 +216,9 @@ static void build_epilogue(struct jit_ctx *ctx)
const u8 fp = bpf2a64[BPF_REG_FP];
const u8 tmp1 = bpf2a64[TMP_REG_1];
const u8 tmp2 = bpf2a64[TMP_REG_2];
int stack_size = MAX_BPF_STACK;
stack_size += 4; /* extra for skb_copy_bits buffer */
stack_size = STACK_ALIGN(stack_size);
/* We're done with BPF stack */
emit(A64_ADD_I(1, A64_SP, A64_SP, stack_size), ctx);
emit(A64_ADD_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
/* Restore fs (x25) and x26 */
emit(A64_POP(fp, A64_R(26), A64_SP), ctx);
@ -591,7 +590,25 @@ emit_cond_jmp:
case BPF_ST | BPF_MEM | BPF_H:
case BPF_ST | BPF_MEM | BPF_B:
case BPF_ST | BPF_MEM | BPF_DW:
goto notyet;
/* Load imm to a register then store it */
ctx->tmp_used = 1;
emit_a64_mov_i(1, tmp2, off, ctx);
emit_a64_mov_i(1, tmp, imm, ctx);
switch (BPF_SIZE(code)) {
case BPF_W:
emit(A64_STR32(tmp, dst, tmp2), ctx);
break;
case BPF_H:
emit(A64_STRH(tmp, dst, tmp2), ctx);
break;
case BPF_B:
emit(A64_STRB(tmp, dst, tmp2), ctx);
break;
case BPF_DW:
emit(A64_STR64(tmp, dst, tmp2), ctx);
break;
}
break;
/* STX: *(size *)(dst + off) = src */
case BPF_STX | BPF_MEM | BPF_W:
@ -658,7 +675,7 @@ emit_cond_jmp:
return -EINVAL;
}
emit_a64_mov_i64(r3, size, ctx);
emit(A64_ADD_I(1, r4, fp, MAX_BPF_STACK), ctx);
emit(A64_SUB_I(1, r4, fp, STACK_SIZE), ctx);
emit_a64_mov_i64(r5, (unsigned long)bpf_load_pointer, ctx);
emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
emit(A64_MOV(1, A64_FP, A64_SP), ctx);

View File

@ -1,6 +1,7 @@
config MN10300
def_bool y
select HAVE_OPROFILE
select HAVE_UID16
select GENERIC_IRQ_SHOW
select ARCH_WANT_IPC_PARSE_VERSION
select HAVE_ARCH_TRACEHOOK
@ -37,9 +38,6 @@ config HIGHMEM
config NUMA
def_bool n
config UID16
def_bool y
config RWSEM_GENERIC_SPINLOCK
def_bool y

View File

@ -23,7 +23,6 @@
#include <stdarg.h>
#include <linux/types.h>
#include <linux/edd.h>
#include <asm/boot.h>
#include <asm/setup.h>
#include "bitops.h"
#include "ctype.h"

View File

@ -19,6 +19,8 @@
#include "video.h"
#include "vesa.h"
#include <uapi/asm/boot.h>
/*
* Common variables
*/

View File

@ -13,6 +13,8 @@
* Select video mode
*/
#include <uapi/asm/boot.h>
#include "boot.h"
#include "video.h"
#include "vesa.h"

View File

@ -509,6 +509,17 @@ END(irq_entries_start)
* tracking that we're in kernel mode.
*/
SWAPGS
/*
* We need to tell lockdep that IRQs are off. We can't do this until
* we fix gsbase, and we should do it before enter_from_user_mode
* (which can take locks). Since TRACE_IRQS_OFF idempotent,
* the simplest way to handle it is to just call it twice if
* we enter from user mode. There's no reason to optimize this since
* TRACE_IRQS_OFF is a no-op if lockdep is off.
*/
TRACE_IRQS_OFF
#ifdef CONFIG_CONTEXT_TRACKING
call enter_from_user_mode
#endif
@ -1049,12 +1060,18 @@ ENTRY(error_entry)
SWAPGS
.Lerror_entry_from_usermode_after_swapgs:
/*
* We need to tell lockdep that IRQs are off. We can't do this until
* we fix gsbase, and we should do it before enter_from_user_mode
* (which can take locks).
*/
TRACE_IRQS_OFF
#ifdef CONFIG_CONTEXT_TRACKING
call enter_from_user_mode
#endif
ret
.Lerror_entry_done:
TRACE_IRQS_OFF
ret

View File

@ -9,20 +9,22 @@
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define __PHYSICAL_MASK ((phys_addr_t)((1ULL << __PHYSICAL_MASK_SHIFT) - 1))
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
/* Cast PAGE_MASK to a signed type so that it is sign-extended if
virtual addresses are 32-bits but physical addresses are larger
(ie, 32-bit PAE). */
#define PHYSICAL_PAGE_MASK (((signed long)PAGE_MASK) & __PHYSICAL_MASK)
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
#define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT)
#define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1))
#define __PHYSICAL_MASK ((phys_addr_t)((1ULL << __PHYSICAL_MASK_SHIFT) - 1))
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
/* Cast *PAGE_MASK to a signed type so that it is sign-extended if
virtual addresses are 32-bits but physical addresses are larger
(ie, 32-bit PAE). */
#define PHYSICAL_PAGE_MASK (((signed long)PAGE_MASK) & __PHYSICAL_MASK)
#define PHYSICAL_PMD_PAGE_MASK (((signed long)PMD_PAGE_MASK) & __PHYSICAL_MASK)
#define PHYSICAL_PUD_PAGE_MASK (((signed long)PUD_PAGE_MASK) & __PHYSICAL_MASK)
#define HPAGE_SHIFT PMD_SHIFT
#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))

View File

@ -279,17 +279,14 @@ static inline pmdval_t native_pmd_val(pmd_t pmd)
static inline pudval_t pud_pfn_mask(pud_t pud)
{
if (native_pud_val(pud) & _PAGE_PSE)
return PUD_PAGE_MASK & PHYSICAL_PAGE_MASK;
return PHYSICAL_PUD_PAGE_MASK;
else
return PTE_PFN_MASK;
}
static inline pudval_t pud_flags_mask(pud_t pud)
{
if (native_pud_val(pud) & _PAGE_PSE)
return ~(PUD_PAGE_MASK & (pudval_t)PHYSICAL_PAGE_MASK);
else
return ~PTE_PFN_MASK;
return ~pud_pfn_mask(pud);
}
static inline pudval_t pud_flags(pud_t pud)
@ -300,17 +297,14 @@ static inline pudval_t pud_flags(pud_t pud)
static inline pmdval_t pmd_pfn_mask(pmd_t pmd)
{
if (native_pmd_val(pmd) & _PAGE_PSE)
return PMD_PAGE_MASK & PHYSICAL_PAGE_MASK;
return PHYSICAL_PMD_PAGE_MASK;
else
return PTE_PFN_MASK;
}
static inline pmdval_t pmd_flags_mask(pmd_t pmd)
{
if (native_pmd_val(pmd) & _PAGE_PSE)
return ~(PMD_PAGE_MASK & (pmdval_t)PHYSICAL_PAGE_MASK);
else
return ~PTE_PFN_MASK;
return ~pmd_pfn_mask(pmd);
}
static inline pmdval_t pmd_flags(pmd_t pmd)

View File

@ -1,7 +1,6 @@
#ifndef _ASM_X86_PLATFORM_H
#define _ASM_X86_PLATFORM_H
#include <asm/pgtable_types.h>
#include <asm/bootparam.h>
struct mpc_bus;

View File

@ -698,3 +698,4 @@ int __init microcode_init(void)
return error;
}
late_initcall(microcode_init);

View File

@ -4,10 +4,22 @@
*/
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/ioport.h>
static int found(u64 start, u64 end, void *data)
{
return 1;
}
static __init int register_e820_pmem(void)
{
char *pmem = "Persistent Memory (legacy)";
struct platform_device *pdev;
int rc;
rc = walk_iomem_res(pmem, IORESOURCE_MEM, 0, -1, NULL, found);
if (rc <= 0)
return 0;
/*
* See drivers/nvdimm/e820.c for the implementation, this is

View File

@ -1250,8 +1250,6 @@ void __init setup_arch(char **cmdline_p)
if (efi_enabled(EFI_BOOT))
efi_apply_memmap_quirks();
#endif
microcode_init();
}
#ifdef CONFIG_X86_32

View File

@ -690,12 +690,15 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
signal_setup_done(failed, ksig, stepping);
}
#ifdef CONFIG_X86_32
#define NR_restart_syscall __NR_restart_syscall
#else /* !CONFIG_X86_32 */
#define NR_restart_syscall \
test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall
#endif /* CONFIG_X86_32 */
static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
{
#if defined(CONFIG_X86_32) || !defined(CONFIG_X86_64)
return __NR_restart_syscall;
#else /* !CONFIG_X86_32 && CONFIG_X86_64 */
return test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall :
__NR_restart_syscall | (regs->orig_ax & __X32_SYSCALL_BIT);
#endif /* CONFIG_X86_32 || !CONFIG_X86_64 */
}
/*
* Note that 'init' is a special process: it doesn't get signals it doesn't
@ -724,7 +727,7 @@ void do_signal(struct pt_regs *regs)
break;
case -ERESTART_RESTARTBLOCK:
regs->ax = NR_restart_syscall;
regs->ax = get_nr_restart_syscall(regs);
regs->ip -= 2;
break;
}

View File

@ -509,7 +509,7 @@ void __inquire_remote_apic(int apicid)
*/
#define UDELAY_10MS_DEFAULT 10000
static unsigned int init_udelay = INT_MAX;
static unsigned int init_udelay = UINT_MAX;
static int __init cpu_init_udelay(char *str)
{
@ -522,14 +522,15 @@ early_param("cpu_init_udelay", cpu_init_udelay);
static void __init smp_quirk_init_udelay(void)
{
/* if cmdline changed it from default, leave it alone */
if (init_udelay != INT_MAX)
if (init_udelay != UINT_MAX)
return;
/* if modern processor, use no delay */
if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF))) {
init_udelay = 0;
return;
}
/* else, use legacy delay */
init_udelay = UDELAY_10MS_DEFAULT;
}

View File

@ -101,19 +101,19 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
switch (type) {
case REG_TYPE_RM:
regno = X86_MODRM_RM(insn->modrm.value);
if (X86_REX_B(insn->rex_prefix.value) == 1)
if (X86_REX_B(insn->rex_prefix.value))
regno += 8;
break;
case REG_TYPE_INDEX:
regno = X86_SIB_INDEX(insn->sib.value);
if (X86_REX_X(insn->rex_prefix.value) == 1)
if (X86_REX_X(insn->rex_prefix.value))
regno += 8;
break;
case REG_TYPE_BASE:
regno = X86_SIB_BASE(insn->sib.value);
if (X86_REX_B(insn->rex_prefix.value) == 1)
if (X86_REX_B(insn->rex_prefix.value))
regno += 8;
break;

View File

@ -50,18 +50,9 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
if (!found)
pci_add_resource(resources, &info->busn);
list_for_each_entry(root_res, &info->resources, list) {
struct resource *res;
struct resource *root;
list_for_each_entry(root_res, &info->resources, list)
pci_add_resource(resources, &root_res->res);
res = &root_res->res;
pci_add_resource(resources, res);
if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
else
root = &iomem_resource;
insert_resource(root, res);
}
return;
default_resources:

View File

@ -2114,7 +2114,8 @@ blk_qc_t submit_bio(int rw, struct bio *bio)
EXPORT_SYMBOL(submit_bio);
/**
* blk_rq_check_limits - Helper function to check a request for the queue limit
* blk_cloned_rq_check_limits - Helper function to check a cloned request
* for new the queue limits
* @q: the queue
* @rq: the request being checked
*
@ -2125,20 +2126,13 @@ EXPORT_SYMBOL(submit_bio);
* after it is inserted to @q, it should be checked against @q before
* the insertion using this generic function.
*
* This function should also be useful for request stacking drivers
* in some cases below, so export this function.
* Request stacking drivers like request-based dm may change the queue
* limits while requests are in the queue (e.g. dm's table swapping).
* Such request stacking drivers should check those requests against
* the new queue limits again when they dispatch those requests,
* although such checkings are also done against the old queue limits
* when submitting requests.
* limits when retrying requests on other queues. Those requests need
* to be checked against the new queue limits again during dispatch.
*/
int blk_rq_check_limits(struct request_queue *q, struct request *rq)
static int blk_cloned_rq_check_limits(struct request_queue *q,
struct request *rq)
{
if (!rq_mergeable(rq))
return 0;
if (blk_rq_sectors(rq) > blk_queue_get_max_sectors(q, rq->cmd_flags)) {
printk(KERN_ERR "%s: over max size limit.\n", __func__);
return -EIO;
@ -2158,7 +2152,6 @@ int blk_rq_check_limits(struct request_queue *q, struct request *rq)
return 0;
}
EXPORT_SYMBOL_GPL(blk_rq_check_limits);
/**
* blk_insert_cloned_request - Helper for stacking drivers to submit a request
@ -2170,7 +2163,7 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
unsigned long flags;
int where = ELEVATOR_INSERT_BACK;
if (blk_rq_check_limits(q, rq))
if (blk_cloned_rq_check_limits(q, rq))
return -EIO;
if (rq->rq_disk &&

View File

@ -103,6 +103,9 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
bvprv = bv;
bvprvp = &bvprv;
sectors += bv.bv_len >> 9;
if (nsegs == 1 && seg_size > front_seg_size)
front_seg_size = seg_size;
continue;
}
new_segment:

View File

@ -91,7 +91,8 @@ void blk_set_default_limits(struct queue_limits *lim)
lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
lim->virt_boundary_mask = 0;
lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors =
BLK_SAFE_MAX_SECTORS;
lim->chunk_sectors = 0;
lim->max_write_same_sectors = 0;
lim->max_discard_sectors = 0;
@ -127,6 +128,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
lim->max_hw_sectors = UINT_MAX;
lim->max_segment_size = UINT_MAX;
lim->max_sectors = UINT_MAX;
lim->max_dev_sectors = UINT_MAX;
lim->max_write_same_sectors = UINT_MAX;
}
EXPORT_SYMBOL(blk_set_stacking_limits);
@ -214,8 +216,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 max_addr)
EXPORT_SYMBOL(blk_queue_bounce_limit);
/**
* blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request
* @limits: the queue limits
* blk_queue_max_hw_sectors - set max sectors for a request for this queue
* @q: the request queue for the device
* @max_hw_sectors: max hardware sectors in the usual 512b unit
*
* Description:
@ -224,13 +226,19 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
* the device driver based upon the capabilities of the I/O
* controller.
*
* max_dev_sectors is a hard limit imposed by the storage device for
* READ/WRITE requests. It is set by the disk driver.
*
* max_sectors is a soft limit imposed by the block layer for
* filesystem type requests. This value can be overridden on a
* per-device basis in /sys/block/<device>/queue/max_sectors_kb.
* The soft limit can not exceed max_hw_sectors.
**/
void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)
void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
{
struct queue_limits *limits = &q->limits;
unsigned int max_sectors;
if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
printk(KERN_INFO "%s: set to minimum %d\n",
@ -238,22 +246,9 @@ void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_
}
limits->max_hw_sectors = max_hw_sectors;
limits->max_sectors = min_t(unsigned int, max_hw_sectors,
BLK_DEF_MAX_SECTORS);
}
EXPORT_SYMBOL(blk_limits_max_hw_sectors);
/**
* blk_queue_max_hw_sectors - set max sectors for a request for this queue
* @q: the request queue for the device
* @max_hw_sectors: max hardware sectors in the usual 512b unit
*
* Description:
* See description for blk_limits_max_hw_sectors().
**/
void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
{
blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);
max_sectors = min_not_zero(max_hw_sectors, limits->max_dev_sectors);
max_sectors = min_t(unsigned int, max_sectors, BLK_DEF_MAX_SECTORS);
limits->max_sectors = max_sectors;
}
EXPORT_SYMBOL(blk_queue_max_hw_sectors);
@ -527,6 +522,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors);
t->max_write_same_sectors = min(t->max_write_same_sectors,
b->max_write_same_sectors);
t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);

View File

@ -205,6 +205,9 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
if (ret < 0)
return ret;
max_hw_sectors_kb = min_not_zero(max_hw_sectors_kb, (unsigned long)
q->limits.max_dev_sectors >> 1);
if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
return -EINVAL;

View File

@ -397,7 +397,7 @@ static int drop_partitions(struct gendisk *disk, struct block_device *bdev)
struct hd_struct *part;
int res;
if (bdev->bd_part_count)
if (bdev->bd_part_count || bdev->bd_super)
return -EBUSY;
res = invalidate_partition(disk, 0);
if (res)

View File

@ -125,7 +125,7 @@ static int aead_wait_for_data(struct sock *sk, unsigned flags)
if (flags & MSG_DONTWAIT)
return -EAGAIN;
set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
for (;;) {
if (signal_pending(current))
@ -139,7 +139,7 @@ static int aead_wait_for_data(struct sock *sk, unsigned flags)
}
finish_wait(sk_sleep(sk), &wait);
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
return err;
}

View File

@ -212,7 +212,7 @@ static int skcipher_wait_for_wmem(struct sock *sk, unsigned flags)
if (flags & MSG_DONTWAIT)
return -EAGAIN;
set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
for (;;) {
if (signal_pending(current))
@ -258,7 +258,7 @@ static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
return -EAGAIN;
}
set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
for (;;) {
if (signal_pending(current))
@ -272,7 +272,7 @@ static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
}
finish_wait(sk_sleep(sk), &wait);
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
return err;
}

View File

@ -58,10 +58,10 @@ config ACPI_CCA_REQUIRED
bool
config ACPI_DEBUGGER
bool "In-kernel debugger (EXPERIMENTAL)"
bool "AML debugger interface (EXPERIMENTAL)"
select ACPI_DEBUG
help
Enable in-kernel debugging facilities: statistics, internal
Enable in-kernel debugging of AML facilities: statistics, internal
object dump, single step control method execution.
This is still under development, currently enabling this only
results in the compilation of the ACPICA debugger files.

View File

@ -233,11 +233,12 @@ static bool add_spa(struct acpi_nfit_desc *acpi_desc,
struct nfit_table_prev *prev,
struct acpi_nfit_system_address *spa)
{
size_t length = min_t(size_t, sizeof(*spa), spa->header.length);
struct device *dev = acpi_desc->dev;
struct nfit_spa *nfit_spa;
list_for_each_entry(nfit_spa, &prev->spas, list) {
if (memcmp(nfit_spa->spa, spa, sizeof(*spa)) == 0) {
if (memcmp(nfit_spa->spa, spa, length) == 0) {
list_move_tail(&nfit_spa->list, &acpi_desc->spas);
return true;
}
@ -259,11 +260,12 @@ static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
struct nfit_table_prev *prev,
struct acpi_nfit_memory_map *memdev)
{
size_t length = min_t(size_t, sizeof(*memdev), memdev->header.length);
struct device *dev = acpi_desc->dev;
struct nfit_memdev *nfit_memdev;
list_for_each_entry(nfit_memdev, &prev->memdevs, list)
if (memcmp(nfit_memdev->memdev, memdev, sizeof(*memdev)) == 0) {
if (memcmp(nfit_memdev->memdev, memdev, length) == 0) {
list_move_tail(&nfit_memdev->list, &acpi_desc->memdevs);
return true;
}
@ -284,11 +286,12 @@ static bool add_dcr(struct acpi_nfit_desc *acpi_desc,
struct nfit_table_prev *prev,
struct acpi_nfit_control_region *dcr)
{
size_t length = min_t(size_t, sizeof(*dcr), dcr->header.length);
struct device *dev = acpi_desc->dev;
struct nfit_dcr *nfit_dcr;
list_for_each_entry(nfit_dcr, &prev->dcrs, list)
if (memcmp(nfit_dcr->dcr, dcr, sizeof(*dcr)) == 0) {
if (memcmp(nfit_dcr->dcr, dcr, length) == 0) {
list_move_tail(&nfit_dcr->list, &acpi_desc->dcrs);
return true;
}
@ -308,11 +311,12 @@ static bool add_bdw(struct acpi_nfit_desc *acpi_desc,
struct nfit_table_prev *prev,
struct acpi_nfit_data_region *bdw)
{
size_t length = min_t(size_t, sizeof(*bdw), bdw->header.length);
struct device *dev = acpi_desc->dev;
struct nfit_bdw *nfit_bdw;
list_for_each_entry(nfit_bdw, &prev->bdws, list)
if (memcmp(nfit_bdw->bdw, bdw, sizeof(*bdw)) == 0) {
if (memcmp(nfit_bdw->bdw, bdw, length) == 0) {
list_move_tail(&nfit_bdw->list, &acpi_desc->bdws);
return true;
}
@ -332,11 +336,12 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc,
struct nfit_table_prev *prev,
struct acpi_nfit_interleave *idt)
{
size_t length = min_t(size_t, sizeof(*idt), idt->header.length);
struct device *dev = acpi_desc->dev;
struct nfit_idt *nfit_idt;
list_for_each_entry(nfit_idt, &prev->idts, list)
if (memcmp(nfit_idt->idt, idt, sizeof(*idt)) == 0) {
if (memcmp(nfit_idt->idt, idt, length) == 0) {
list_move_tail(&nfit_idt->list, &acpi_desc->idts);
return true;
}
@ -356,11 +361,12 @@ static bool add_flush(struct acpi_nfit_desc *acpi_desc,
struct nfit_table_prev *prev,
struct acpi_nfit_flush_address *flush)
{
size_t length = min_t(size_t, sizeof(*flush), flush->header.length);
struct device *dev = acpi_desc->dev;
struct nfit_flush *nfit_flush;
list_for_each_entry(nfit_flush, &prev->flushes, list)
if (memcmp(nfit_flush->flush, flush, sizeof(*flush)) == 0) {
if (memcmp(nfit_flush->flush, flush, length) == 0) {
list_move_tail(&nfit_flush->list, &acpi_desc->flushes);
return true;
}
@ -655,7 +661,7 @@ static ssize_t revision_show(struct device *dev,
struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
return sprintf(buf, "%d\n", acpi_desc->nfit->header.revision);
return sprintf(buf, "%d\n", acpi_desc->acpi_header.revision);
}
static DEVICE_ATTR_RO(revision);
@ -1652,7 +1658,6 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
data = (u8 *) acpi_desc->nfit;
end = data + sz;
data += sizeof(struct acpi_table_nfit);
while (!IS_ERR_OR_NULL(data))
data = add_table(acpi_desc, &prev, data, end);
@ -1748,13 +1753,29 @@ static int acpi_nfit_add(struct acpi_device *adev)
return PTR_ERR(acpi_desc);
}
acpi_desc->nfit = (struct acpi_table_nfit *) tbl;
/*
* Save the acpi header for later and then skip it,
* making nfit point to the first nfit table header.
*/
acpi_desc->acpi_header = *tbl;
acpi_desc->nfit = (void *) tbl + sizeof(struct acpi_table_nfit);
sz -= sizeof(struct acpi_table_nfit);
/* Evaluate _FIT and override with that if present */
status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
if (ACPI_SUCCESS(status) && buf.length > 0) {
acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer;
sz = buf.length;
union acpi_object *obj;
/*
* Adjust for the acpi_object header of the _FIT
*/
obj = buf.pointer;
if (obj->type == ACPI_TYPE_BUFFER) {
acpi_desc->nfit =
(struct acpi_nfit_header *)obj->buffer.pointer;
sz = obj->buffer.length;
} else
dev_dbg(dev, "%s invalid type %d, ignoring _FIT\n",
__func__, (int) obj->type);
}
rc = acpi_nfit_init(acpi_desc, sz);
@ -1777,7 +1798,8 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
{
struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev);
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_table_nfit *nfit_saved;
struct acpi_nfit_header *nfit_saved;
union acpi_object *obj;
struct device *dev = &adev->dev;
acpi_status status;
int ret;
@ -1808,12 +1830,19 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
}
nfit_saved = acpi_desc->nfit;
acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer;
ret = acpi_nfit_init(acpi_desc, buf.length);
if (!ret) {
/* Merge failed, restore old nfit, and exit */
acpi_desc->nfit = nfit_saved;
dev_err(dev, "failed to merge updated NFIT\n");
obj = buf.pointer;
if (obj->type == ACPI_TYPE_BUFFER) {
acpi_desc->nfit =
(struct acpi_nfit_header *)obj->buffer.pointer;
ret = acpi_nfit_init(acpi_desc, obj->buffer.length);
if (ret) {
/* Merge failed, restore old nfit, and exit */
acpi_desc->nfit = nfit_saved;
dev_err(dev, "failed to merge updated NFIT\n");
}
} else {
/* Bad _FIT, restore old nfit */
dev_err(dev, "Invalid _FIT\n");
}
kfree(buf.pointer);

View File

@ -96,7 +96,8 @@ struct nfit_mem {
struct acpi_nfit_desc {
struct nvdimm_bus_descriptor nd_desc;
struct acpi_table_nfit *nfit;
struct acpi_table_header acpi_header;
struct acpi_nfit_header *nfit;
struct mutex spa_map_mutex;
struct mutex init_mutex;
struct list_head spa_maps;

View File

@ -768,6 +768,13 @@ static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
else
continue;
/*
* Some legacy x86 host bridge drivers use iomem_resource and
* ioport_resource as default resource pool, skip it.
*/
if (res == root)
continue;
conflict = insert_resource_conflict(root, res);
if (conflict) {
dev_info(&info->bridge->dev,

View File

@ -1775,10 +1775,10 @@ int genpd_dev_pm_attach(struct device *dev)
}
pd = of_genpd_get_from_provider(&pd_args);
of_node_put(pd_args.np);
if (IS_ERR(pd)) {
dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
__func__, PTR_ERR(pd));
of_node_put(dev->of_node);
return -EPROBE_DEFER;
}
@ -1796,7 +1796,6 @@ int genpd_dev_pm_attach(struct device *dev)
if (ret < 0) {
dev_err(dev, "failed to add to PM domain %s: %d",
pd->name, ret);
of_node_put(dev->of_node);
goto out;
}

View File

@ -160,9 +160,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
struct gpd_timing_data *td;
s64 constraint_ns;
if (!pdd->dev->driver)
continue;
/*
* Check if the device is allowed to be off long enough for the
* domain to turn off and on (that's how much time it will

View File

@ -18,6 +18,7 @@ struct nullb_cmd {
struct bio *bio;
unsigned int tag;
struct nullb_queue *nq;
struct hrtimer timer;
};
struct nullb_queue {
@ -49,17 +50,6 @@ static int null_major;
static int nullb_indexes;
static struct kmem_cache *ppa_cache;
struct completion_queue {
struct llist_head list;
struct hrtimer timer;
};
/*
* These are per-cpu for now, they will need to be configured by the
* complete_queues parameter and appropriately mapped.
*/
static DEFINE_PER_CPU(struct completion_queue, completion_queues);
enum {
NULL_IRQ_NONE = 0,
NULL_IRQ_SOFTIRQ = 1,
@ -142,8 +132,8 @@ static const struct kernel_param_ops null_irqmode_param_ops = {
device_param_cb(irqmode, &null_irqmode_param_ops, &irqmode, S_IRUGO);
MODULE_PARM_DESC(irqmode, "IRQ completion handler. 0-none, 1-softirq, 2-timer");
static int completion_nsec = 10000;
module_param(completion_nsec, int, S_IRUGO);
static unsigned long completion_nsec = 10000;
module_param(completion_nsec, ulong, S_IRUGO);
MODULE_PARM_DESC(completion_nsec, "Time in ns to complete a request in hardware. Default: 10,000ns");
static int hw_queue_depth = 64;
@ -180,6 +170,8 @@ static void free_cmd(struct nullb_cmd *cmd)
put_tag(cmd->nq, cmd->tag);
}
static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer);
static struct nullb_cmd *__alloc_cmd(struct nullb_queue *nq)
{
struct nullb_cmd *cmd;
@ -190,6 +182,11 @@ static struct nullb_cmd *__alloc_cmd(struct nullb_queue *nq)
cmd = &nq->cmds[tag];
cmd->tag = tag;
cmd->nq = nq;
if (irqmode == NULL_IRQ_TIMER) {
hrtimer_init(&cmd->timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
cmd->timer.function = null_cmd_timer_expired;
}
return cmd;
}
@ -220,6 +217,8 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait)
static void end_cmd(struct nullb_cmd *cmd)
{
struct request_queue *q = NULL;
switch (queue_mode) {
case NULL_Q_MQ:
blk_mq_end_request(cmd->rq, 0);
@ -230,55 +229,37 @@ static void end_cmd(struct nullb_cmd *cmd)
break;
case NULL_Q_BIO:
bio_endio(cmd->bio);
break;
goto free_cmd;
}
if (cmd->rq)
q = cmd->rq->q;
/* Restart queue if needed, as we are freeing a tag */
if (q && !q->mq_ops && blk_queue_stopped(q)) {
unsigned long flags;
spin_lock_irqsave(q->queue_lock, flags);
if (blk_queue_stopped(q))
blk_start_queue(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
free_cmd:
free_cmd(cmd);
}
static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
{
struct completion_queue *cq;
struct llist_node *entry;
struct nullb_cmd *cmd;
cq = &per_cpu(completion_queues, smp_processor_id());
while ((entry = llist_del_all(&cq->list)) != NULL) {
entry = llist_reverse_order(entry);
do {
struct request_queue *q = NULL;
cmd = container_of(entry, struct nullb_cmd, ll_list);
entry = entry->next;
if (cmd->rq)
q = cmd->rq->q;
end_cmd(cmd);
if (q && !q->mq_ops && blk_queue_stopped(q)) {
spin_lock(q->queue_lock);
if (blk_queue_stopped(q))
blk_start_queue(q);
spin_unlock(q->queue_lock);
}
} while (entry);
}
end_cmd(container_of(timer, struct nullb_cmd, timer));
return HRTIMER_NORESTART;
}
static void null_cmd_end_timer(struct nullb_cmd *cmd)
{
struct completion_queue *cq = &per_cpu(completion_queues, get_cpu());
ktime_t kt = ktime_set(0, completion_nsec);
cmd->ll_list.next = NULL;
if (llist_add(&cmd->ll_list, &cq->list)) {
ktime_t kt = ktime_set(0, completion_nsec);
hrtimer_start(&cq->timer, kt, HRTIMER_MODE_REL_PINNED);
}
put_cpu();
hrtimer_start(&cmd->timer, kt, HRTIMER_MODE_REL);
}
static void null_softirq_done_fn(struct request *rq)
@ -376,6 +357,10 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx,
{
struct nullb_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
if (irqmode == NULL_IRQ_TIMER) {
hrtimer_init(&cmd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
cmd->timer.function = null_cmd_timer_expired;
}
cmd->rq = bd->rq;
cmd->nq = hctx->driver_data;
@ -813,19 +798,6 @@ static int __init null_init(void)
mutex_init(&lock);
/* Initialize a separate list for each CPU for issuing softirqs */
for_each_possible_cpu(i) {
struct completion_queue *cq = &per_cpu(completion_queues, i);
init_llist_head(&cq->list);
if (irqmode != NULL_IRQ_TIMER)
continue;
hrtimer_init(&cq->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
cq->timer.function = null_cmd_timer_expired;
}
null_major = register_blkdev(0, "nullb");
if (null_major < 0)
return null_major;

View File

@ -3442,6 +3442,7 @@ static void rbd_queue_workfn(struct work_struct *work)
goto err_rq;
}
img_request->rq = rq;
snapc = NULL; /* img_request consumes a ref */
if (op_type == OBJ_OP_DISCARD)
result = rbd_img_request_fill(img_request, OBJ_REQUEST_NODATA,

View File

@ -976,10 +976,14 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
new_policy.governor = gov;
/* Use the default policy if its valid. */
if (cpufreq_driver->setpolicy)
cpufreq_parse_governor(gov->name, &new_policy.policy, NULL);
/* Use the default policy if there is no last_policy. */
if (cpufreq_driver->setpolicy) {
if (policy->last_policy)
new_policy.policy = policy->last_policy;
else
cpufreq_parse_governor(gov->name, &new_policy.policy,
NULL);
}
/* set default policy */
return cpufreq_set_policy(policy, &new_policy);
}
@ -1330,6 +1334,8 @@ static void cpufreq_offline_prepare(unsigned int cpu)
if (has_target())
strncpy(policy->last_governor, policy->governor->name,
CPUFREQ_NAME_LEN);
else
policy->last_policy = policy->policy;
} else if (cpu == policy->cpu) {
/* Nominate new CPU */
policy->cpu = cpumask_any(policy->cpus);

View File

@ -409,7 +409,7 @@ static int ccm_nx_decrypt(struct aead_request *req,
processed += to_process;
} while (processed < nbytes);
rc = memcmp(csbcpb->cpb.aes_ccm.out_pat_or_mac, priv->oauth_tag,
rc = crypto_memneq(csbcpb->cpb.aes_ccm.out_pat_or_mac, priv->oauth_tag,
authsize) ? -EBADMSG : 0;
out:
spin_unlock_irqrestore(&nx_ctx->lock, irq_flags);

View File

@ -21,6 +21,7 @@
#include <crypto/internal/aead.h>
#include <crypto/aes.h>
#include <crypto/algapi.h>
#include <crypto/scatterwalk.h>
#include <linux/module.h>
#include <linux/types.h>
@ -418,7 +419,7 @@ mac:
itag, req->src, req->assoclen + nbytes,
crypto_aead_authsize(crypto_aead_reqtfm(req)),
SCATTERWALK_FROM_SG);
rc = memcmp(itag, otag,
rc = crypto_memneq(itag, otag,
crypto_aead_authsize(crypto_aead_reqtfm(req))) ?
-EBADMSG : 0;
}

View File

@ -977,7 +977,7 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
} else
oicv = (char *)&edesc->link_tbl[0];
err = memcmp(oicv, icv, authsize) ? -EBADMSG : 0;
err = crypto_memneq(oicv, icv, authsize) ? -EBADMSG : 0;
}
kfree(edesc);

View File

@ -113,13 +113,16 @@ static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
static int mmio_74xx_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mmio_74xx_gpio_ids, &pdev->dev);
const struct of_device_id *of_id;
struct mmio_74xx_gpio_priv *priv;
struct resource *res;
void __iomem *dat;
int err;
of_id = of_match_device(mmio_74xx_gpio_ids, &pdev->dev);
if (!of_id)
return -ENODEV;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

View File

@ -1122,8 +1122,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
/* MPUIO is a bit different, reading IRQ status clears it */
if (bank->is_mpuio) {
irqc->irq_ack = dummy_irq_chip.irq_ack;
irqc->irq_mask = irq_gc_mask_set_bit;
irqc->irq_unmask = irq_gc_mask_clr_bit;
if (!bank->regs->wkup_en)
irqc->irq_set_wake = NULL;
}

View File

@ -167,6 +167,8 @@ static int palmas_gpio_probe(struct platform_device *pdev)
const struct palmas_device_data *dev_data;
match = of_match_device(of_palmas_gpio_match, &pdev->dev);
if (!match)
return -ENODEV;
dev_data = match->data;
if (!dev_data)
dev_data = &palmas_dev_data;

View File

@ -187,11 +187,15 @@ MODULE_DEVICE_TABLE(of, syscon_gpio_ids);
static int syscon_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *of_id = of_match_device(syscon_gpio_ids, dev);
const struct of_device_id *of_id;
struct syscon_gpio_priv *priv;
struct device_node *np = dev->of_node;
int ret;
of_id = of_match_device(syscon_gpio_ids, dev);
if (!of_id)
return -ENODEV;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;

View File

@ -375,6 +375,60 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
}
#endif
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
static int dbg_gpio_show(struct seq_file *s, void *unused)
{
int i;
int j;
for (i = 0; i < tegra_gpio_bank_count; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
seq_printf(s,
"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
i, j,
tegra_gpio_readl(GPIO_CNF(gpio)),
tegra_gpio_readl(GPIO_OE(gpio)),
tegra_gpio_readl(GPIO_OUT(gpio)),
tegra_gpio_readl(GPIO_IN(gpio)),
tegra_gpio_readl(GPIO_INT_STA(gpio)),
tegra_gpio_readl(GPIO_INT_ENB(gpio)),
tegra_gpio_readl(GPIO_INT_LVL(gpio)));
}
}
return 0;
}
static int dbg_gpio_open(struct inode *inode, struct file *file)
{
return single_open(file, dbg_gpio_show, &inode->i_private);
}
static const struct file_operations debug_fops = {
.open = dbg_gpio_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void tegra_gpio_debuginit(void)
{
(void) debugfs_create_file("tegra_gpio", S_IRUGO,
NULL, NULL, &debug_fops);
}
#else
static inline void tegra_gpio_debuginit(void)
{
}
#endif
static struct irq_chip tegra_gpio_irq_chip = {
.name = "GPIO",
.irq_ack = tegra_gpio_irq_ack,
@ -519,6 +573,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
spin_lock_init(&bank->lvl_lock[j]);
}
tegra_gpio_debuginit();
return 0;
}
@ -536,52 +592,3 @@ static int __init tegra_gpio_init(void)
return platform_driver_register(&tegra_gpio_driver);
}
postcore_initcall(tegra_gpio_init);
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
static int dbg_gpio_show(struct seq_file *s, void *unused)
{
int i;
int j;
for (i = 0; i < tegra_gpio_bank_count; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
seq_printf(s,
"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
i, j,
tegra_gpio_readl(GPIO_CNF(gpio)),
tegra_gpio_readl(GPIO_OE(gpio)),
tegra_gpio_readl(GPIO_OUT(gpio)),
tegra_gpio_readl(GPIO_IN(gpio)),
tegra_gpio_readl(GPIO_INT_STA(gpio)),
tegra_gpio_readl(GPIO_INT_ENB(gpio)),
tegra_gpio_readl(GPIO_INT_LVL(gpio)));
}
}
return 0;
}
static int dbg_gpio_open(struct inode *inode, struct file *file)
{
return single_open(file, dbg_gpio_show, &inode->i_private);
}
static const struct file_operations debug_fops = {
.open = dbg_gpio_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init tegra_gpio_debuginit(void)
{
(void) debugfs_create_file("tegra_gpio", S_IRUGO,
NULL, NULL, &debug_fops);
return 0;
}
late_initcall(tegra_gpio_debuginit);
#endif

View File

@ -233,7 +233,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name)
for (i = 0; i != chip->ngpio; ++i) {
struct gpio_desc *gpio = &chip->desc[i];
if (!gpio->name)
if (!gpio->name || !name)
continue;
if (!strcmp(gpio->name, name)) {

View File

@ -539,6 +539,7 @@ struct amdgpu_bo {
/* Constant after initialization */
struct amdgpu_device *adev;
struct drm_gem_object gem_base;
struct amdgpu_bo *parent;
struct ttm_bo_kmap_obj dma_buf_vmap;
pid_t pid;
@ -955,6 +956,8 @@ struct amdgpu_vm {
struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS];
/* for interval tree */
spinlock_t it_lock;
/* protecting freed */
spinlock_t freed_lock;
};
struct amdgpu_vm_manager {

View File

@ -222,6 +222,8 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
}
p->uf.bo = gem_to_amdgpu_bo(gobj);
amdgpu_bo_ref(p->uf.bo);
drm_gem_object_unreference_unlocked(gobj);
p->uf.offset = fence_data->offset;
} else {
ret = -EINVAL;
@ -487,7 +489,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
amdgpu_ib_free(parser->adev, &parser->ibs[i]);
kfree(parser->ibs);
if (parser->uf.bo)
drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
amdgpu_bo_unref(&parser->uf.bo);
}
static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
@ -776,7 +778,7 @@ static int amdgpu_cs_free_job(struct amdgpu_job *job)
amdgpu_ib_free(job->adev, &job->ibs[i]);
kfree(job->ibs);
if (job->uf.bo)
drm_gem_object_unreference_unlocked(&job->uf.bo->gem_base);
amdgpu_bo_unref(&job->uf.bo);
return 0;
}

View File

@ -73,6 +73,8 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
struct drm_crtc *crtc = &amdgpuCrtc->base;
unsigned long flags;
unsigned i;
int vpos, hpos, stat, min_udelay;
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
amdgpu_flip_wait_fence(adev, &work->excl);
for (i = 0; i < work->shared_count; ++i)
@ -81,6 +83,41 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
/* We borrow the event spin lock for protecting flip_status */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
/* If this happens to execute within the "virtually extended" vblank
* interval before the start of the real vblank interval then it needs
* to delay programming the mmio flip until the real vblank is entered.
* This prevents completing a flip too early due to the way we fudge
* our vblank counter and vblank timestamps in order to work around the
* problem that the hw fires vblank interrupts before actual start of
* vblank (when line buffer refilling is done for a frame). It
* complements the fudging logic in amdgpu_get_crtc_scanoutpos() for
* timestamping and amdgpu_get_vblank_counter_kms() for vblank counts.
*
* In practice this won't execute very often unless on very fast
* machines because the time window for this to happen is very small.
*/
for (;;) {
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
* start in hpos, and to the "fudged earlier" vblank start in
* vpos.
*/
stat = amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id,
GET_DISTANCE_TO_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&crtc->hwmode);
if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) ||
!(vpos >= 0 && hpos <= 0))
break;
/* Sleep at least until estimated real start of hw vblank */
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
usleep_range(min_udelay, 2 * min_udelay);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
};
/* do the flip (mmio) */
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
/* set the flip status */
@ -109,7 +146,7 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
} else
DRM_ERROR("failed to reserve buffer after flip\n");
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
amdgpu_bo_unref(&work->old_rbo);
kfree(work->shared);
kfree(work);
}
@ -148,8 +185,8 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
obj = old_amdgpu_fb->obj;
/* take a reference to the old object */
drm_gem_object_reference(obj);
work->old_rbo = gem_to_amdgpu_bo(obj);
amdgpu_bo_ref(work->old_rbo);
new_amdgpu_fb = to_amdgpu_framebuffer(fb);
obj = new_amdgpu_fb->obj;
@ -222,7 +259,7 @@ pflip_cleanup:
amdgpu_bo_unreserve(new_rbo);
cleanup:
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
amdgpu_bo_unref(&work->old_rbo);
fence_put(work->excl);
for (i = 0; i < work->shared_count; ++i)
fence_put(work->shared[i]);
@ -712,6 +749,15 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
* \param dev Device to query.
* \param pipe Crtc to query.
* \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
* For driver internal use only also supports these flags:
*
* USE_REAL_VBLANKSTART to use the real start of vblank instead
* of a fudged earlier start of vblank.
*
* GET_DISTANCE_TO_VBLANKSTART to return distance to the
* fudged earlier start of vblank in *vpos and the distance
* to true start of vblank in *hpos.
*
* \param *vpos Location where vertical scanout position should be stored.
* \param *hpos Location where horizontal scanout position should go.
* \param *stime Target location for timestamp taken immediately before
@ -776,10 +822,40 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
vbl_end = 0;
}
/* Called from driver internal vblank counter query code? */
if (flags & GET_DISTANCE_TO_VBLANKSTART) {
/* Caller wants distance from real vbl_start in *hpos */
*hpos = *vpos - vbl_start;
}
/* Fudge vblank to start a few scanlines earlier to handle the
* problem that vblank irqs fire a few scanlines before start
* of vblank. Some driver internal callers need the true vblank
* start to be used and signal this via the USE_REAL_VBLANKSTART flag.
*
* The cause of the "early" vblank irq is that the irq is triggered
* by the line buffer logic when the line buffer read position enters
* the vblank, whereas our crtc scanout position naturally lags the
* line buffer read position.
*/
if (!(flags & USE_REAL_VBLANKSTART))
vbl_start -= adev->mode_info.crtcs[pipe]->lb_vblank_lead_lines;
/* Test scanout position against vblank region. */
if ((*vpos < vbl_start) && (*vpos >= vbl_end))
in_vbl = false;
/* In vblank? */
if (in_vbl)
ret |= DRM_SCANOUTPOS_IN_VBLANK;
/* Called from driver internal vblank counter query code? */
if (flags & GET_DISTANCE_TO_VBLANKSTART) {
/* Caller wants distance from fudged earlier vbl_start */
*vpos -= vbl_start;
return ret;
}
/* Check if inside vblank area and apply corrective offsets:
* vpos will then be >=0 in video scanout area, but negative
* within vblank area, counting down the number of lines until
@ -795,32 +871,6 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
/* Correct for shifted end of vbl at vbl_end. */
*vpos = *vpos - vbl_end;
/* In vblank? */
if (in_vbl)
ret |= DRM_SCANOUTPOS_IN_VBLANK;
/* Is vpos outside nominal vblank area, but less than
* 1/100 of a frame height away from start of vblank?
* If so, assume this isn't a massively delayed vblank
* interrupt, but a vblank interrupt that fired a few
* microseconds before true start of vblank. Compensate
* by adding a full frame duration to the final timestamp.
* Happens, e.g., on ATI R500, R600.
*
* We only do this if DRM_CALLED_FROM_VBLIRQ.
*/
if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
vbl_start = mode->crtc_vdisplay;
vtotal = mode->crtc_vtotal;
if (vbl_start - *vpos < vtotal / 100) {
*vpos -= vtotal;
/* Signal this correction as "applied". */
ret |= 0x8;
}
}
return ret;
}

View File

@ -235,8 +235,9 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
AMDGPU_GEM_USERPTR_REGISTER))
return -EINVAL;
if (!(args->flags & AMDGPU_GEM_USERPTR_ANONONLY) ||
!(args->flags & AMDGPU_GEM_USERPTR_REGISTER)) {
if (!(args->flags & AMDGPU_GEM_USERPTR_READONLY) && (
!(args->flags & AMDGPU_GEM_USERPTR_ANONONLY) ||
!(args->flags & AMDGPU_GEM_USERPTR_REGISTER))) {
/* if we want to write to it we must require anonymous
memory and install a MMU notifier */

View File

@ -611,13 +611,59 @@ void amdgpu_driver_preclose_kms(struct drm_device *dev,
u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe)
{
struct amdgpu_device *adev = dev->dev_private;
int vpos, hpos, stat;
u32 count;
if (pipe >= adev->mode_info.num_crtc) {
DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
return amdgpu_display_vblank_get_counter(adev, pipe);
/* The hw increments its frame counter at start of vsync, not at start
* of vblank, as is required by DRM core vblank counter handling.
* Cook the hw count here to make it appear to the caller as if it
* incremented at start of vblank. We measure distance to start of
* vblank in vpos. vpos therefore will be >= 0 between start of vblank
* and start of vsync, so vpos >= 0 means to bump the hw frame counter
* result by 1 to give the proper appearance to caller.
*/
if (adev->mode_info.crtcs[pipe]) {
/* Repeat readout if needed to provide stable result if
* we cross start of vsync during the queries.
*/
do {
count = amdgpu_display_vblank_get_counter(adev, pipe);
/* Ask amdgpu_get_crtc_scanoutpos to return vpos as
* distance to start of vblank, instead of regular
* vertical scanout pos.
*/
stat = amdgpu_get_crtc_scanoutpos(
dev, pipe, GET_DISTANCE_TO_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&adev->mode_info.crtcs[pipe]->base.hwmode);
} while (count != amdgpu_display_vblank_get_counter(adev, pipe));
if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) {
DRM_DEBUG_VBL("Query failed! stat %d\n", stat);
} else {
DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n",
pipe, vpos);
/* Bump counter if we are at >= leading edge of vblank,
* but before vsync where vpos would turn negative and
* the hw counter really increments.
*/
if (vpos >= 0)
count++;
}
} else {
/* Fallback to use value as is. */
count = amdgpu_display_vblank_get_counter(adev, pipe);
DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
}
return count;
}
/**

View File

@ -407,6 +407,7 @@ struct amdgpu_crtc {
u32 line_time;
u32 wm_low;
u32 wm_high;
u32 lb_vblank_lead_lines;
struct drm_display_mode hw_mode;
};
@ -528,6 +529,10 @@ struct amdgpu_framebuffer {
#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
((em) == ATOM_ENCODER_MODE_DP_MST))
/* Driver internal use only flags of amdgpu_get_crtc_scanoutpos() */
#define USE_REAL_VBLANKSTART (1 << 30)
#define GET_DISTANCE_TO_VBLANKSTART (1 << 31)
void amdgpu_link_encoder_connector(struct drm_device *dev);
struct drm_connector *

View File

@ -100,6 +100,7 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
list_del_init(&bo->list);
mutex_unlock(&bo->adev->gem.mutex);
drm_gem_object_release(&bo->gem_base);
amdgpu_bo_unref(&bo->parent);
kfree(bo->metadata);
kfree(bo);
}

View File

@ -587,9 +587,13 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm,
uint32_t flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem);
int r;
if (gtt->userptr)
amdgpu_ttm_tt_pin_userptr(ttm);
if (gtt->userptr) {
r = amdgpu_ttm_tt_pin_userptr(ttm);
if (r) {
DRM_ERROR("failed to pin userptr\n");
return r;
}
}
gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT);
if (!ttm->num_pages) {
WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
@ -797,11 +801,12 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
if (mem && mem->mem_type != TTM_PL_SYSTEM)
flags |= AMDGPU_PTE_VALID;
if (mem && mem->mem_type == TTM_PL_TT)
if (mem && mem->mem_type == TTM_PL_TT) {
flags |= AMDGPU_PTE_SYSTEM;
if (!ttm || ttm->caching_state == tt_cached)
flags |= AMDGPU_PTE_SNOOPED;
if (ttm->caching_state == tt_cached)
flags |= AMDGPU_PTE_SNOOPED;
}
if (adev->asic_type >= CHIP_TOPAZ)
flags |= AMDGPU_PTE_EXECUTABLE;

View File

@ -885,17 +885,21 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping;
int r;
spin_lock(&vm->freed_lock);
while (!list_empty(&vm->freed)) {
mapping = list_first_entry(&vm->freed,
struct amdgpu_bo_va_mapping, list);
list_del(&mapping->list);
spin_unlock(&vm->freed_lock);
r = amdgpu_vm_bo_update_mapping(adev, vm, mapping, 0, 0, NULL);
kfree(mapping);
if (r)
return r;
spin_lock(&vm->freed_lock);
}
spin_unlock(&vm->freed_lock);
return 0;
}
@ -1079,6 +1083,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
if (r)
goto error_free;
/* Keep a reference to the page table to avoid freeing
* them up in the wrong order.
*/
pt->parent = amdgpu_bo_ref(vm->page_directory);
r = amdgpu_vm_clear_bo(adev, pt);
if (r) {
amdgpu_bo_unref(&pt);
@ -1150,10 +1159,13 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
spin_unlock(&vm->it_lock);
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
if (valid)
if (valid) {
spin_lock(&vm->freed_lock);
list_add(&mapping->list, &vm->freed);
else
spin_unlock(&vm->freed_lock);
} else {
kfree(mapping);
}
return 0;
}
@ -1186,7 +1198,9 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
interval_tree_remove(&mapping->it, &vm->va);
spin_unlock(&vm->it_lock);
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
spin_lock(&vm->freed_lock);
list_add(&mapping->list, &vm->freed);
spin_unlock(&vm->freed_lock);
}
list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) {
list_del(&mapping->list);
@ -1247,6 +1261,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
INIT_LIST_HEAD(&vm->cleared);
INIT_LIST_HEAD(&vm->freed);
spin_lock_init(&vm->it_lock);
spin_lock_init(&vm->freed_lock);
pd_size = amdgpu_vm_directory_size(adev);
pd_entries = amdgpu_vm_num_pdes(adev);

View File

@ -1250,7 +1250,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
u32 pixel_period;
u32 line_time = 0;
u32 latency_watermark_a = 0, latency_watermark_b = 0;
u32 tmp, wm_mask;
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
if (amdgpu_crtc->base.enabled && num_heads && mode) {
pixel_period = 1000000 / (u32)mode->clock;
@ -1333,6 +1333,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
(adev->mode_info.disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
}
lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* select wm A */
@ -1357,6 +1358,8 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
amdgpu_crtc->line_time = line_time;
amdgpu_crtc->wm_high = latency_watermark_a;
amdgpu_crtc->wm_low = latency_watermark_b;
/* Save number of lines the linebuffer leads before the scanout */
amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines;
}
/**

View File

@ -1238,7 +1238,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
u32 pixel_period;
u32 line_time = 0;
u32 latency_watermark_a = 0, latency_watermark_b = 0;
u32 tmp, wm_mask;
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
if (amdgpu_crtc->base.enabled && num_heads && mode) {
pixel_period = 1000000 / (u32)mode->clock;
@ -1321,6 +1321,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
(adev->mode_info.disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
}
lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* select wm A */
@ -1345,6 +1346,8 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
amdgpu_crtc->line_time = line_time;
amdgpu_crtc->wm_high = latency_watermark_a;
amdgpu_crtc->wm_low = latency_watermark_b;
/* Save number of lines the linebuffer leads before the scanout */
amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines;
}
/**

View File

@ -1193,7 +1193,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
u32 pixel_period;
u32 line_time = 0;
u32 latency_watermark_a = 0, latency_watermark_b = 0;
u32 tmp, wm_mask;
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
if (amdgpu_crtc->base.enabled && num_heads && mode) {
pixel_period = 1000000 / (u32)mode->clock;
@ -1276,6 +1276,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
(adev->mode_info.disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
}
lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* select wm A */
@ -1302,6 +1303,8 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
amdgpu_crtc->line_time = line_time;
amdgpu_crtc->wm_high = latency_watermark_a;
amdgpu_crtc->wm_low = latency_watermark_b;
/* Save number of lines the linebuffer leads before the scanout */
amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines;
}
/**

View File

@ -513,7 +513,7 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
WREG32(mmVM_L2_CNTL3, tmp);
/* setup context0 */
WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12);
WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, (adev->mc.gtt_end >> 12) - 1);
WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12);
WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12);
WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(adev->dummy_page.addr >> 12));

View File

@ -657,7 +657,7 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
WREG32(mmVM_L2_CNTL4, tmp);
/* setup context0 */
WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12);
WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, (adev->mc.gtt_end >> 12) - 1);
WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12);
WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12);
WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(adev->dummy_page.addr >> 12));

View File

@ -288,6 +288,7 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity)
*/
static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
{
struct amd_gpu_scheduler *sched = sched_job->sched;
struct amd_sched_entity *entity = sched_job->s_entity;
bool added, first = false;
@ -302,7 +303,7 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
/* first job wakes up scheduler */
if (first)
amd_sched_wakeup(sched_job->sched);
amd_sched_wakeup(sched);
return added;
}
@ -318,9 +319,9 @@ void amd_sched_entity_push_job(struct amd_sched_job *sched_job)
{
struct amd_sched_entity *entity = sched_job->s_entity;
trace_amd_sched_job(sched_job);
wait_event(entity->sched->job_scheduled,
amd_sched_entity_in(sched_job));
trace_amd_sched_job(sched_job);
}
/**

View File

@ -160,6 +160,11 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}
if (!file_priv->allowed_master) {
ret = drm_new_set_master(dev, file_priv);
goto out_unlock;
}
file_priv->minor->master = drm_master_get(file_priv->master);
file_priv->is_master = 1;
if (dev->driver->master_set) {

View File

@ -125,6 +125,60 @@ static int drm_cpu_valid(void)
return 1;
}
/**
* drm_new_set_master - Allocate a new master object and become master for the
* associated master realm.
*
* @dev: The associated device.
* @fpriv: File private identifying the client.
*
* This function must be called with dev::struct_mutex held.
* Returns negative error code on failure. Zero on success.
*/
int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
{
struct drm_master *old_master;
int ret;
lockdep_assert_held_once(&dev->master_mutex);
/* create a new master */
fpriv->minor->master = drm_master_create(fpriv->minor);
if (!fpriv->minor->master)
return -ENOMEM;
/* take another reference for the copy in the local file priv */
old_master = fpriv->master;
fpriv->master = drm_master_get(fpriv->minor->master);
if (dev->driver->master_create) {
ret = dev->driver->master_create(dev, fpriv->master);
if (ret)
goto out_err;
}
if (dev->driver->master_set) {
ret = dev->driver->master_set(dev, fpriv, true);
if (ret)
goto out_err;
}
fpriv->is_master = 1;
fpriv->allowed_master = 1;
fpriv->authenticated = 1;
if (old_master)
drm_master_put(&old_master);
return 0;
out_err:
/* drop both references and restore old master on failure */
drm_master_put(&fpriv->minor->master);
drm_master_put(&fpriv->master);
fpriv->master = old_master;
return ret;
}
/**
* Called whenever a process opens /dev/drm.
*
@ -191,35 +245,9 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
mutex_lock(&dev->master_mutex);
if (drm_is_primary_client(priv) && !priv->minor->master) {
/* create a new master */
priv->minor->master = drm_master_create(priv->minor);
if (!priv->minor->master) {
ret = -ENOMEM;
ret = drm_new_set_master(dev, priv);
if (ret)
goto out_close;
}
priv->is_master = 1;
/* take another reference for the copy in the local file priv */
priv->master = drm_master_get(priv->minor->master);
priv->authenticated = 1;
if (dev->driver->master_create) {
ret = dev->driver->master_create(dev, priv->master);
if (ret) {
/* drop both references if this fails */
drm_master_put(&priv->minor->master);
drm_master_put(&priv->master);
goto out_close;
}
}
if (dev->driver->master_set) {
ret = dev->driver->master_set(dev, priv, true);
if (ret) {
/* drop both references if this fails */
drm_master_put(&priv->minor->master);
drm_master_put(&priv->master);
goto out_close;
}
}
} else if (drm_is_primary_client(priv)) {
/* get a reference to the master */
priv->master = drm_master_get(priv->minor->master);

View File

@ -980,7 +980,8 @@ static void send_vblank_event(struct drm_device *dev,
struct drm_pending_vblank_event *e,
unsigned long seq, struct timeval *now)
{
WARN_ON_SMP(!spin_is_locked(&dev->event_lock));
assert_spin_locked(&dev->event_lock);
e->event.sequence = seq;
e->event.tv_sec = now->tv_sec;
e->event.tv_usec = now->tv_usec;
@ -992,6 +993,57 @@ static void send_vblank_event(struct drm_device *dev,
e->event.sequence);
}
/**
* drm_arm_vblank_event - arm vblank event after pageflip
* @dev: DRM device
* @pipe: CRTC index
* @e: the event to prepare to send
*
* A lot of drivers need to generate vblank events for the very next vblank
* interrupt. For example when the page flip interrupt happens when the page
* flip gets armed, but not when it actually executes within the next vblank
* period. This helper function implements exactly the required vblank arming
* behaviour.
*
* Caller must hold event lock. Caller must also hold a vblank reference for
* the event @e, which will be dropped when the next vblank arrives.
*
* This is the legacy version of drm_crtc_arm_vblank_event().
*/
void drm_arm_vblank_event(struct drm_device *dev, unsigned int pipe,
struct drm_pending_vblank_event *e)
{
assert_spin_locked(&dev->event_lock);
e->pipe = pipe;
e->event.sequence = drm_vblank_count(dev, pipe);
list_add_tail(&e->base.link, &dev->vblank_event_list);
}
EXPORT_SYMBOL(drm_arm_vblank_event);
/**
* drm_crtc_arm_vblank_event - arm vblank event after pageflip
* @crtc: the source CRTC of the vblank event
* @e: the event to send
*
* A lot of drivers need to generate vblank events for the very next vblank
* interrupt. For example when the page flip interrupt happens when the page
* flip gets armed, but not when it actually executes within the next vblank
* period. This helper function implements exactly the required vblank arming
* behaviour.
*
* Caller must hold event lock. Caller must also hold a vblank reference for
* the event @e, which will be dropped when the next vblank arrives.
*
* This is the native KMS version of drm_arm_vblank_event().
*/
void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
struct drm_pending_vblank_event *e)
{
drm_arm_vblank_event(crtc->dev, drm_crtc_index(crtc), e);
}
EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
/**
* drm_send_vblank_event - helper to send vblank event after pageflip
* @dev: DRM device

View File

@ -1210,8 +1210,16 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
if (i915_gem_request_completed(req, true))
return 0;
timeout_expire = timeout ?
jiffies + nsecs_to_jiffies_timeout((u64)*timeout) : 0;
timeout_expire = 0;
if (timeout) {
if (WARN_ON(*timeout < 0))
return -EINVAL;
if (*timeout == 0)
return -ETIME;
timeout_expire = jiffies + nsecs_to_jiffies_timeout(*timeout);
}
if (INTEL_INFO(dev_priv)->gen >= 6)
gen6_rps_boost(dev_priv, rps, req->emitted_jiffies);

View File

@ -642,11 +642,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
}
/* check for L-shaped memory aka modified enhanced addressing */
if (IS_GEN4(dev)) {
uint32_t ddc2 = I915_READ(DCC2);
if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE))
dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
if (IS_GEN4(dev) &&
!(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) {
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
}
if (dcc == 0xffffffff) {
@ -675,16 +674,35 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
* matching, which was the case for the swizzling required in
* the table above, or from the 1-ch value being less than
* the minimum size of a rank.
*
* Reports indicate that the swizzling actually
* varies depending upon page placement inside the
* channels, i.e. we see swizzled pages where the
* banks of memory are paired and unswizzled on the
* uneven portion, so leave that as unknown.
*/
if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) {
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
} else {
if (I915_READ16(C0DRB3) == I915_READ16(C1DRB3)) {
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9;
}
}
if (swizzle_x == I915_BIT_6_SWIZZLE_UNKNOWN ||
swizzle_y == I915_BIT_6_SWIZZLE_UNKNOWN) {
/* Userspace likes to explode if it sees unknown swizzling,
* so lie. We will finish the lie when reporting through
* the get-tiling-ioctl by reporting the physical swizzle
* mode as unknown instead.
*
* As we don't strictly know what the swizzling is, it may be
* bit17 dependent, and so we need to also prevent the pages
* from being moved.
*/
dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
}
dev_priv->mm.bit_6_swizzle_x = swizzle_x;
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
}

View File

@ -12582,7 +12582,6 @@ intel_pipe_config_compare(struct drm_device *dev,
if (INTEL_INFO(dev)->gen < 8) {
PIPE_CONF_CHECK_M_N(dp_m_n);
PIPE_CONF_CHECK_I(has_drrs);
if (current_config->has_drrs)
PIPE_CONF_CHECK_M_N(dp_m2_n2);
} else

View File

@ -4962,7 +4962,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
enum intel_display_power_domain power_domain;
enum irqreturn ret = IRQ_NONE;
if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
if (intel_dig_port->base.type != INTEL_OUTPUT_EDP &&
intel_dig_port->base.type != INTEL_OUTPUT_HDMI)
intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {

View File

@ -64,8 +64,7 @@ static void imx_drm_driver_lastclose(struct drm_device *drm)
{
struct imx_drm_device *imxdrm = drm->dev_private;
if (imxdrm->fbhelper)
drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
}
static int imx_drm_driver_unload(struct drm_device *drm)
@ -334,7 +333,7 @@ err_kms:
* imx_drm_add_crtc - add a new crtc
*/
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
struct imx_drm_crtc **new_crtc,
struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
struct device_node *port)
{
@ -373,7 +372,7 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
drm_crtc_helper_add(crtc,
imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
drm_crtc_init(drm, crtc,
drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
return 0;

View File

@ -9,6 +9,7 @@ struct drm_display_mode;
struct drm_encoder;
struct drm_fbdev_cma;
struct drm_framebuffer;
struct drm_plane;
struct imx_drm_crtc;
struct platform_device;
@ -24,7 +25,7 @@ struct imx_drm_crtc_helper_funcs {
};
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
struct imx_drm_crtc **new_crtc,
struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
struct device_node *port);
int imx_drm_remove_crtc(struct imx_drm_crtc *);

View File

@ -721,6 +721,7 @@ static const struct of_device_id imx_tve_dt_ids[] = {
{ .compatible = "fsl,imx53-tve", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_tve_dt_ids);
static struct platform_driver imx_tve_driver = {
.probe = imx_tve_probe,

View File

@ -212,7 +212,8 @@ static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)
spin_lock_irqsave(&drm->event_lock, flags);
if (ipu_crtc->page_flip_event)
drm_send_vblank_event(drm, -1, ipu_crtc->page_flip_event);
drm_crtc_send_vblank_event(&ipu_crtc->base,
ipu_crtc->page_flip_event);
ipu_crtc->page_flip_event = NULL;
imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);
spin_unlock_irqrestore(&drm->event_lock, flags);
@ -349,7 +350,6 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
int dp = -EINVAL;
int ret;
int id;
ret = ipu_get_resources(ipu_crtc, pdata);
if (ret) {
@ -358,18 +358,23 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
return ret;
}
if (pdata->dp >= 0)
dp = IPU_DP_FLOW_SYNC_BG;
ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0,
DRM_PLANE_TYPE_PRIMARY);
if (IS_ERR(ipu_crtc->plane[0])) {
ret = PTR_ERR(ipu_crtc->plane[0]);
goto err_put_resources;
}
ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
&ipu_crtc_helper_funcs, ipu_crtc->dev->of_node);
&ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
ipu_crtc->dev->of_node);
if (ret) {
dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
goto err_put_resources;
}
if (pdata->dp >= 0)
dp = IPU_DP_FLOW_SYNC_BG;
id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu,
pdata->dma[0], dp, BIT(id), true);
ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
if (ret) {
dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
@ -379,10 +384,10 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
/* If this crtc is using the DP, add an overlay plane */
if (pdata->dp >= 0 && pdata->dma[1] > 0) {
ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev, ipu,
pdata->dma[1],
IPU_DP_FLOW_SYNC_FG,
BIT(id), false);
ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1],
IPU_DP_FLOW_SYNC_FG,
drm_crtc_mask(&ipu_crtc->base),
DRM_PLANE_TYPE_OVERLAY);
if (IS_ERR(ipu_crtc->plane[1]))
ipu_crtc->plane[1] = NULL;
}
@ -407,28 +412,6 @@ err_put_resources:
return ret;
}
static struct device_node *ipu_drm_get_port_by_id(struct device_node *parent,
int port_id)
{
struct device_node *port;
int id, ret;
port = of_get_child_by_name(parent, "port");
while (port) {
ret = of_property_read_u32(port, "reg", &id);
if (!ret && id == port_id)
return port;
do {
port = of_get_next_child(parent, port);
if (!port)
return NULL;
} while (of_node_cmp(port->name, "port"));
}
return NULL;
}
static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
{
struct ipu_client_platformdata *pdata = dev->platform_data;
@ -470,23 +453,11 @@ static const struct component_ops ipu_crtc_ops = {
static int ipu_drm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ipu_client_platformdata *pdata = dev->platform_data;
int ret;
if (!dev->platform_data)
return -EINVAL;
if (!dev->of_node) {
/* Associate crtc device with the corresponding DI port node */
dev->of_node = ipu_drm_get_port_by_id(dev->parent->of_node,
pdata->di + 2);
if (!dev->of_node) {
dev_err(dev, "missing port@%d node in %s\n",
pdata->di + 2, dev->parent->of_node->full_name);
return -ENODEV;
}
}
ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
if (ret)
return ret;

View File

@ -381,7 +381,7 @@ static struct drm_plane_funcs ipu_plane_funcs = {
struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
int dma, int dp, unsigned int possible_crtcs,
bool priv)
enum drm_plane_type type)
{
struct ipu_plane *ipu_plane;
int ret;
@ -399,10 +399,9 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
ipu_plane->dma = dma;
ipu_plane->dp_flow = dp;
ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs,
&ipu_plane_funcs, ipu_plane_formats,
ARRAY_SIZE(ipu_plane_formats),
priv);
ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
&ipu_plane_funcs, ipu_plane_formats,
ARRAY_SIZE(ipu_plane_formats), type);
if (ret) {
DRM_ERROR("failed to initialize plane\n");
kfree(ipu_plane);

View File

@ -34,7 +34,7 @@ struct ipu_plane {
struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
int dma, int dp, unsigned int possible_crtcs,
bool priv);
enum drm_plane_type type);
/* Init IDMAC, DMFC, DP */
int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,

View File

@ -54,7 +54,11 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
if (imxpd->panel && imxpd->panel->funcs &&
imxpd->panel->funcs->get_modes) {
struct drm_display_info *di = &connector->display_info;
num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
if (!imxpd->bus_format && di->num_bus_formats)
imxpd->bus_format = di->bus_formats[0];
if (num_modes > 0)
return num_modes;
}

View File

@ -829,7 +829,6 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
struct drm_device *dev = drm->dev;
struct nouveau_page_flip_state *s;
unsigned long flags;
int crtcid = -1;
spin_lock_irqsave(&dev->event_lock, flags);
@ -841,15 +840,19 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
if (s->event) {
/* Vblank timestamps/counts are only correct on >= NV-50 */
if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
crtcid = s->crtc;
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
drm_arm_vblank_event(dev, s->crtc, s->event);
} else {
drm_send_vblank_event(dev, s->crtc, s->event);
drm_send_vblank_event(dev, crtcid, s->event);
/* Give up ownership of vblank for page-flipped crtc */
drm_vblank_put(dev, s->crtc);
}
}
else {
/* Give up ownership of vblank for page-flipped crtc */
drm_vblank_put(dev, s->crtc);
}
/* Give up ownership of vblank for page-flipped crtc */
drm_vblank_put(dev, s->crtc);
list_del(&s->head);
if (ps)

View File

@ -8472,7 +8472,7 @@ restart_ih:
if (queue_dp)
schedule_work(&rdev->dp_work);
if (queue_hotplug)
schedule_work(&rdev->hotplug_work);
schedule_delayed_work(&rdev->hotplug_work, 0);
if (queue_reset) {
rdev->needs_reset = true;
wake_up_all(&rdev->fence_queue);
@ -9630,6 +9630,9 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
(rdev->disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
}
/* Save number of lines the linebuffer leads before the scanout */
radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* select wm A */

View File

@ -2372,6 +2372,9 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
c.full = dfixed_div(c, a);
priority_b_mark = dfixed_trunc(c);
priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK;
/* Save number of lines the linebuffer leads before the scanout */
radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* select wm A */
@ -5344,7 +5347,7 @@ restart_ih:
if (queue_dp)
schedule_work(&rdev->dp_work);
if (queue_hotplug)
schedule_work(&rdev->hotplug_work);
schedule_delayed_work(&rdev->hotplug_work, 0);
if (queue_hdmi)
schedule_work(&rdev->audio_work);
if (queue_thermal && rdev->pm.dpm_enabled)

View File

@ -806,7 +806,7 @@ int r100_irq_process(struct radeon_device *rdev)
status = r100_irq_ack(rdev);
}
if (queue_hotplug)
schedule_work(&rdev->hotplug_work);
schedule_delayed_work(&rdev->hotplug_work, 0);
if (rdev->msi_enabled) {
switch (rdev->family) {
case CHIP_RS400:
@ -3217,6 +3217,9 @@ void r100_bandwidth_update(struct radeon_device *rdev)
uint32_t pixel_bytes1 = 0;
uint32_t pixel_bytes2 = 0;
/* Guess line buffer size to be 8192 pixels */
u32 lb_size = 8192;
if (!rdev->mode_info.mode_config_initialized)
return;
@ -3631,6 +3634,13 @@ void r100_bandwidth_update(struct radeon_device *rdev)
DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n",
(unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL));
}
/* Save number of lines the linebuffer leads before the scanout */
if (mode1)
rdev->mode_info.crtcs[0]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode1->crtc_hdisplay);
if (mode2)
rdev->mode_info.crtcs[1]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode2->crtc_hdisplay);
}
int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)

View File

@ -4276,7 +4276,7 @@ restart_ih:
WREG32(IH_RB_RPTR, rptr);
}
if (queue_hotplug)
schedule_work(&rdev->hotplug_work);
schedule_delayed_work(&rdev->hotplug_work, 0);
if (queue_hdmi)
schedule_work(&rdev->audio_work);
if (queue_thermal && rdev->pm.dpm_enabled)

View File

@ -2414,7 +2414,7 @@ struct radeon_device {
struct r600_ih ih; /* r6/700 interrupt ring */
struct radeon_rlc rlc;
struct radeon_mec mec;
struct work_struct hotplug_work;
struct delayed_work hotplug_work;
struct work_struct dp_work;
struct work_struct audio_work;
int num_crtc; /* number of crtcs */

View File

@ -54,6 +54,9 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
/* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */
{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e50,
PCI_VENDOR_ID_IBM, 0x0550, 1},
/* Intel 82855PM host bridge / RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] needs AGPMode 1 (Thinkpad T40p) */
{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66,
PCI_VENDOR_ID_IBM, 0x054d, 1},
/* Intel 82855PM host bridge / Mobility M7 needs AGPMode 1 */
{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c57,
PCI_VENDOR_ID_IBM, 0x0530, 1},

View File

@ -1234,13 +1234,32 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
if (r < 0)
return connector_status_disconnected;
if (radeon_connector->detected_hpd_without_ddc) {
force = true;
radeon_connector->detected_hpd_without_ddc = false;
}
if (!force && radeon_check_hpd_status_unchanged(connector)) {
ret = connector->status;
goto exit;
}
if (radeon_connector->ddc_bus)
if (radeon_connector->ddc_bus) {
dret = radeon_ddc_probe(radeon_connector, false);
/* Sometimes the pins required for the DDC probe on DVI
* connectors don't make contact at the same time that the ones
* for HPD do. If the DDC probe fails even though we had an HPD
* signal, try again later */
if (!dret && !force &&
connector->status != connector_status_connected) {
DRM_DEBUG_KMS("hpd detected without ddc, retrying in 1 second\n");
radeon_connector->detected_hpd_without_ddc = true;
schedule_delayed_work(&rdev->hotplug_work,
msecs_to_jiffies(1000));
goto exit;
}
}
if (dret) {
radeon_connector->detected_by_load = false;
radeon_connector_free_edid(connector);

View File

@ -322,7 +322,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
* to complete in this vblank?
*/
if (update_pending &&
(DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
(DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev,
crtc_id,
USE_REAL_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&rdev->mode_info.crtcs[crtc_id]->base.hwmode)) &&
((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
@ -401,6 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
struct drm_crtc *crtc = &radeon_crtc->base;
unsigned long flags;
int r;
int vpos, hpos, stat, min_udelay;
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
down_read(&rdev->exclusive_lock);
if (work->fence) {
@ -437,6 +441,41 @@ static void radeon_flip_work_func(struct work_struct *__work)
/* set the proper interrupt */
radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
/* If this happens to execute within the "virtually extended" vblank
* interval before the start of the real vblank interval then it needs
* to delay programming the mmio flip until the real vblank is entered.
* This prevents completing a flip too early due to the way we fudge
* our vblank counter and vblank timestamps in order to work around the
* problem that the hw fires vblank interrupts before actual start of
* vblank (when line buffer refilling is done for a frame). It
* complements the fudging logic in radeon_get_crtc_scanoutpos() for
* timestamping and radeon_get_vblank_counter_kms() for vblank counts.
*
* In practice this won't execute very often unless on very fast
* machines because the time window for this to happen is very small.
*/
for (;;) {
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
* start in hpos, and to the "fudged earlier" vblank start in
* vpos.
*/
stat = radeon_get_crtc_scanoutpos(rdev->ddev, work->crtc_id,
GET_DISTANCE_TO_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&crtc->hwmode);
if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) ||
!(vpos >= 0 && hpos <= 0))
break;
/* Sleep at least until estimated real start of hw vblank */
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
usleep_range(min_udelay, 2 * min_udelay);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
};
/* do the flip (mmio) */
radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
@ -1768,6 +1807,15 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
* \param dev Device to query.
* \param crtc Crtc to query.
* \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
* For driver internal use only also supports these flags:
*
* USE_REAL_VBLANKSTART to use the real start of vblank instead
* of a fudged earlier start of vblank.
*
* GET_DISTANCE_TO_VBLANKSTART to return distance to the
* fudged earlier start of vblank in *vpos and the distance
* to true start of vblank in *hpos.
*
* \param *vpos Location where vertical scanout position should be stored.
* \param *hpos Location where horizontal scanout position should go.
* \param *stime Target location for timestamp taken immediately before
@ -1911,10 +1959,40 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
vbl_end = 0;
}
/* Called from driver internal vblank counter query code? */
if (flags & GET_DISTANCE_TO_VBLANKSTART) {
/* Caller wants distance from real vbl_start in *hpos */
*hpos = *vpos - vbl_start;
}
/* Fudge vblank to start a few scanlines earlier to handle the
* problem that vblank irqs fire a few scanlines before start
* of vblank. Some driver internal callers need the true vblank
* start to be used and signal this via the USE_REAL_VBLANKSTART flag.
*
* The cause of the "early" vblank irq is that the irq is triggered
* by the line buffer logic when the line buffer read position enters
* the vblank, whereas our crtc scanout position naturally lags the
* line buffer read position.
*/
if (!(flags & USE_REAL_VBLANKSTART))
vbl_start -= rdev->mode_info.crtcs[pipe]->lb_vblank_lead_lines;
/* Test scanout position against vblank region. */
if ((*vpos < vbl_start) && (*vpos >= vbl_end))
in_vbl = false;
/* In vblank? */
if (in_vbl)
ret |= DRM_SCANOUTPOS_IN_VBLANK;
/* Called from driver internal vblank counter query code? */
if (flags & GET_DISTANCE_TO_VBLANKSTART) {
/* Caller wants distance from fudged earlier vbl_start */
*vpos -= vbl_start;
return ret;
}
/* Check if inside vblank area and apply corrective offsets:
* vpos will then be >=0 in video scanout area, but negative
* within vblank area, counting down the number of lines until
@ -1930,31 +2008,5 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
/* Correct for shifted end of vbl at vbl_end. */
*vpos = *vpos - vbl_end;
/* In vblank? */
if (in_vbl)
ret |= DRM_SCANOUTPOS_IN_VBLANK;
/* Is vpos outside nominal vblank area, but less than
* 1/100 of a frame height away from start of vblank?
* If so, assume this isn't a massively delayed vblank
* interrupt, but a vblank interrupt that fired a few
* microseconds before true start of vblank. Compensate
* by adding a full frame duration to the final timestamp.
* Happens, e.g., on ATI R500, R600.
*
* We only do this if DRM_CALLED_FROM_VBLIRQ.
*/
if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
vbl_start = mode->crtc_vdisplay;
vtotal = mode->crtc_vtotal;
if (vbl_start - *vpos < vtotal / 100) {
*vpos -= vtotal;
/* Signal this correction as "applied". */
ret |= 0x8;
}
}
return ret;
}

View File

@ -74,7 +74,7 @@ irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
static void radeon_hotplug_work_func(struct work_struct *work)
{
struct radeon_device *rdev = container_of(work, struct radeon_device,
hotplug_work);
hotplug_work.work);
struct drm_device *dev = rdev->ddev;
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector;
@ -302,7 +302,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
}
}
INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
INIT_DELAYED_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
INIT_WORK(&rdev->dp_work, radeon_dp_work_func);
INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
@ -310,7 +310,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
r = drm_irq_install(rdev->ddev, rdev->ddev->pdev->irq);
if (r) {
rdev->irq.installed = false;
flush_work(&rdev->hotplug_work);
flush_delayed_work(&rdev->hotplug_work);
return r;
}
@ -333,7 +333,7 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
rdev->irq.installed = false;
if (rdev->msi_enabled)
pci_disable_msi(rdev->pdev);
flush_work(&rdev->hotplug_work);
flush_delayed_work(&rdev->hotplug_work);
}
}

View File

@ -755,6 +755,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
*/
u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
{
int vpos, hpos, stat;
u32 count;
struct radeon_device *rdev = dev->dev_private;
if (crtc < 0 || crtc >= rdev->num_crtc) {
@ -762,7 +764,53 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
return -EINVAL;
}
return radeon_get_vblank_counter(rdev, crtc);
/* The hw increments its frame counter at start of vsync, not at start
* of vblank, as is required by DRM core vblank counter handling.
* Cook the hw count here to make it appear to the caller as if it
* incremented at start of vblank. We measure distance to start of
* vblank in vpos. vpos therefore will be >= 0 between start of vblank
* and start of vsync, so vpos >= 0 means to bump the hw frame counter
* result by 1 to give the proper appearance to caller.
*/
if (rdev->mode_info.crtcs[crtc]) {
/* Repeat readout if needed to provide stable result if
* we cross start of vsync during the queries.
*/
do {
count = radeon_get_vblank_counter(rdev, crtc);
/* Ask radeon_get_crtc_scanoutpos to return vpos as
* distance to start of vblank, instead of regular
* vertical scanout pos.
*/
stat = radeon_get_crtc_scanoutpos(
dev, crtc, GET_DISTANCE_TO_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&rdev->mode_info.crtcs[crtc]->base.hwmode);
} while (count != radeon_get_vblank_counter(rdev, crtc));
if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) {
DRM_DEBUG_VBL("Query failed! stat %d\n", stat);
}
else {
DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n",
crtc, vpos);
/* Bump counter if we are at >= leading edge of vblank,
* but before vsync where vpos would turn negative and
* the hw counter really increments.
*/
if (vpos >= 0)
count++;
}
}
else {
/* Fallback to use value as is. */
count = radeon_get_vblank_counter(rdev, crtc);
DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
}
return count;
}
/**

View File

@ -367,6 +367,7 @@ struct radeon_crtc {
u32 line_time;
u32 wm_low;
u32 wm_high;
u32 lb_vblank_lead_lines;
struct drm_display_mode hw_mode;
enum radeon_output_csc output_csc;
};
@ -553,6 +554,7 @@ struct radeon_connector {
void *con_priv;
bool dac_load_detect;
bool detected_by_load; /* if the connection status was determined by load */
bool detected_hpd_without_ddc; /* if an HPD signal was detected on DVI, but ddc probing failed */
uint16_t connector_object_id;
struct radeon_hpd hpd;
struct radeon_router router;
@ -686,6 +688,9 @@ struct atom_voltage_table
struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES];
};
/* Driver internal use only flags of radeon_get_crtc_scanoutpos() */
#define USE_REAL_VBLANKSTART (1 << 30)
#define GET_DISTANCE_TO_VBLANKSTART (1 << 31)
extern void
radeon_add_atom_connector(struct drm_device *dev,

View File

@ -1756,7 +1756,9 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
*/
for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
if (rdev->pm.active_crtcs & (1 << crtc)) {
vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0,
vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev,
crtc,
USE_REAL_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&rdev->mode_info.crtcs[crtc]->base.hwmode);
if ((vbl_status & DRM_SCANOUTPOS_VALID) &&

View File

@ -813,7 +813,7 @@ int rs600_irq_process(struct radeon_device *rdev)
status = rs600_irq_ack(rdev);
}
if (queue_hotplug)
schedule_work(&rdev->hotplug_work);
schedule_delayed_work(&rdev->hotplug_work, 0);
if (queue_hdmi)
schedule_work(&rdev->audio_work);
if (rdev->msi_enabled) {

View File

@ -207,6 +207,9 @@ void rs690_line_buffer_adjust(struct radeon_device *rdev,
{
u32 tmp;
/* Guess line buffer size to be 8192 pixels */
u32 lb_size = 8192;
/*
* Line Buffer Setup
* There is a single line buffer shared by both display controllers.
@ -243,6 +246,13 @@ void rs690_line_buffer_adjust(struct radeon_device *rdev,
tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
}
WREG32(R_006520_DC_LB_MEMORY_SPLIT, tmp);
/* Save number of lines the linebuffer leads before the scanout */
if (mode1)
rdev->mode_info.crtcs[0]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode1->crtc_hdisplay);
if (mode2)
rdev->mode_info.crtcs[1]->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode2->crtc_hdisplay);
}
struct rs690_watermark {

View File

@ -2376,6 +2376,9 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
c.full = dfixed_div(c, a);
priority_b_mark = dfixed_trunc(c);
priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK;
/* Save number of lines the linebuffer leads before the scanout */
radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* select wm A */
@ -6848,7 +6851,7 @@ restart_ih:
if (queue_dp)
schedule_work(&rdev->dp_work);
if (queue_hotplug)
schedule_work(&rdev->hotplug_work);
schedule_delayed_work(&rdev->hotplug_work, 0);
if (queue_thermal && rdev->pm.dpm_enabled)
schedule_work(&rdev->pm.dpm.thermal.work);
rdev->ih.rptr = rptr;

View File

@ -67,6 +67,7 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj,
* VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
*/
vma->vm_flags &= ~VM_PFNMAP;
vma->vm_pgoff = 0;
ret = dma_mmap_attrs(drm->dev, vma, rk_obj->kvaddr, rk_obj->dma_addr,
obj->size, &rk_obj->dma_attrs);

Some files were not shown because too many files have changed in this diff Show More