mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-23 05:18:55 +00:00
* Change DEV to EDGE * Renaming patches dev folder to edge * Move patches into subdir where they will be archived. * Relink patch directories properly
4987 lines
163 KiB
Diff
4987 lines
163 KiB
Diff
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
|
|
index 8a532f4453f26..09aecec47003a 100644
|
|
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt
|
|
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
|
|
@@ -49,6 +49,8 @@ Optional properties:
|
|
error caused by stop clock(fifo full)
|
|
Valid range = [0:0x7]. if not present, default value is 0.
|
|
applied to compatible "mediatek,mt2701-mmc".
|
|
+- resets: Phandle and reset specifier pair to softreset line of MSDC IP.
|
|
+- reset-names: Should be "hrst".
|
|
|
|
Examples:
|
|
mmc0: mmc@11230000 {
|
|
diff --git a/Documentation/filesystems/affs.txt b/Documentation/filesystems/affs.txt
|
|
index 71b63c2b98410..a8f1a58e36922 100644
|
|
--- a/Documentation/filesystems/affs.txt
|
|
+++ b/Documentation/filesystems/affs.txt
|
|
@@ -93,13 +93,15 @@ The Amiga protection flags RWEDRWEDHSPARWED are handled as follows:
|
|
|
|
- R maps to r for user, group and others. On directories, R implies x.
|
|
|
|
- - If both W and D are allowed, w will be set.
|
|
+ - W maps to w.
|
|
|
|
- E maps to x.
|
|
|
|
- - H and P are always retained and ignored under Linux.
|
|
+ - D is ignored.
|
|
|
|
- - A is always reset when a file is written to.
|
|
+ - H, S and P are always retained and ignored under Linux.
|
|
+
|
|
+ - A is cleared when a file is written to.
|
|
|
|
User id and group id will be used unless set[gu]id are given as mount
|
|
options. Since most of the Amiga file systems are single user systems
|
|
@@ -111,11 +113,13 @@ Linux -> Amiga:
|
|
|
|
The Linux rwxrwxrwx file mode is handled as follows:
|
|
|
|
- - r permission will set R for user, group and others.
|
|
+ - r permission will allow R for user, group and others.
|
|
+
|
|
+ - w permission will allow W for user, group and others.
|
|
|
|
- - w permission will set W and D for user, group and others.
|
|
+ - x permission of the user will allow E for plain files.
|
|
|
|
- - x permission of the user will set E for plain files.
|
|
+ - D will be allowed for user, group and others.
|
|
|
|
- All other flags (suid, sgid, ...) are ignored and will
|
|
not be retained.
|
|
diff --git a/Makefile b/Makefile
|
|
index 418814b108ae6..7bdfb21bb9269 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 5
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 63
|
|
+SUBLEVEL = 64
|
|
EXTRAVERSION =
|
|
NAME = Kleptomaniac Octopus
|
|
|
|
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
|
|
index 661fd842ea97d..79849f37e782c 100644
|
|
--- a/arch/arc/kernel/perf_event.c
|
|
+++ b/arch/arc/kernel/perf_event.c
|
|
@@ -562,7 +562,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
|
|
{
|
|
struct arc_reg_pct_build pct_bcr;
|
|
struct arc_reg_cc_build cc_bcr;
|
|
- int i, has_interrupts;
|
|
+ int i, has_interrupts, irq;
|
|
int counter_size; /* in bits */
|
|
|
|
union cc_name {
|
|
@@ -637,13 +637,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
|
|
.attr_groups = arc_pmu->attr_groups,
|
|
};
|
|
|
|
- if (has_interrupts) {
|
|
- int irq = platform_get_irq(pdev, 0);
|
|
-
|
|
- if (irq < 0) {
|
|
- pr_err("Cannot get IRQ number for the platform\n");
|
|
- return -ENODEV;
|
|
- }
|
|
+ if (has_interrupts && (irq = platform_get_irq(pdev, 0) >= 0)) {
|
|
|
|
arc_pmu->irq = irq;
|
|
|
|
@@ -652,9 +646,9 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
|
|
this_cpu_ptr(&arc_pmu_cpu));
|
|
|
|
on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
|
|
-
|
|
- } else
|
|
+ } else {
|
|
arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
|
|
+ }
|
|
|
|
/*
|
|
* perf parser doesn't really like '-' symbol in events name, so let's
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
|
|
index dac51e98204c0..7cd8c3f52b471 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
|
|
@@ -686,6 +686,8 @@
|
|
clocks = <&pericfg CLK_PERI_MSDC30_0_PD>,
|
|
<&topckgen CLK_TOP_MSDC50_0_SEL>;
|
|
clock-names = "source", "hclk";
|
|
+ resets = <&pericfg MT7622_PERI_MSDC0_SW_RST>;
|
|
+ reset-names = "hrst";
|
|
status = "disabled";
|
|
};
|
|
|
|
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
|
|
index 712c15de6ab9f..6b304acf506fe 100644
|
|
--- a/arch/mips/kernel/smp-bmips.c
|
|
+++ b/arch/mips/kernel/smp-bmips.c
|
|
@@ -241,6 +241,8 @@ static int bmips_boot_secondary(int cpu, struct task_struct *idle)
|
|
*/
|
|
static void bmips_init_secondary(void)
|
|
{
|
|
+ bmips_cpu_setup();
|
|
+
|
|
switch (current_cpu_type()) {
|
|
case CPU_BMIPS4350:
|
|
case CPU_BMIPS4380:
|
|
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
|
|
index 6a25364600266..8282d0feb0b21 100644
|
|
--- a/arch/mips/kernel/traps.c
|
|
+++ b/arch/mips/kernel/traps.c
|
|
@@ -1240,6 +1240,18 @@ static int enable_restore_fp_context(int msa)
|
|
err = own_fpu_inatomic(1);
|
|
if (msa && !err) {
|
|
enable_msa();
|
|
+ /*
|
|
+ * with MSA enabled, userspace can see MSACSR
|
|
+ * and MSA regs, but the values in them are from
|
|
+ * other task before current task, restore them
|
|
+ * from saved fp/msa context
|
|
+ */
|
|
+ write_msa_csr(current->thread.fpu.msacsr);
|
|
+ /*
|
|
+ * own_fpu_inatomic(1) just restore low 64bit,
|
|
+ * fix the high 64bit
|
|
+ */
|
|
+ init_msa_upper();
|
|
set_thread_flag(TIF_USEDMSA);
|
|
set_thread_flag(TIF_MSA_CTX_LIVE);
|
|
}
|
|
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
|
|
index 89b9c851d8227..c4785a456dedc 100644
|
|
--- a/arch/mips/mm/c-r4k.c
|
|
+++ b/arch/mips/mm/c-r4k.c
|
|
@@ -1676,7 +1676,11 @@ static void setup_scache(void)
|
|
printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
|
|
scache_size >> 10,
|
|
way_string[c->scache.ways], c->scache.linesz);
|
|
+
|
|
+ if (current_cpu_type() == CPU_BMIPS5000)
|
|
+ c->options |= MIPS_CPU_INCLUSIVE_CACHES;
|
|
}
|
|
+
|
|
#else
|
|
if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
|
|
panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
|
|
diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h
|
|
index 50b4ce8cddfdc..918f0ba4f4d20 100644
|
|
--- a/arch/s390/include/asm/percpu.h
|
|
+++ b/arch/s390/include/asm/percpu.h
|
|
@@ -29,7 +29,7 @@
|
|
typedef typeof(pcp) pcp_op_T__; \
|
|
pcp_op_T__ old__, new__, prev__; \
|
|
pcp_op_T__ *ptr__; \
|
|
- preempt_disable(); \
|
|
+ preempt_disable_notrace(); \
|
|
ptr__ = raw_cpu_ptr(&(pcp)); \
|
|
prev__ = *ptr__; \
|
|
do { \
|
|
@@ -37,7 +37,7 @@
|
|
new__ = old__ op (val); \
|
|
prev__ = cmpxchg(ptr__, old__, new__); \
|
|
} while (prev__ != old__); \
|
|
- preempt_enable(); \
|
|
+ preempt_enable_notrace(); \
|
|
new__; \
|
|
})
|
|
|
|
@@ -68,7 +68,7 @@
|
|
typedef typeof(pcp) pcp_op_T__; \
|
|
pcp_op_T__ val__ = (val); \
|
|
pcp_op_T__ old__, *ptr__; \
|
|
- preempt_disable(); \
|
|
+ preempt_disable_notrace(); \
|
|
ptr__ = raw_cpu_ptr(&(pcp)); \
|
|
if (__builtin_constant_p(val__) && \
|
|
((szcast)val__ > -129) && ((szcast)val__ < 128)) { \
|
|
@@ -84,7 +84,7 @@
|
|
: [val__] "d" (val__) \
|
|
: "cc"); \
|
|
} \
|
|
- preempt_enable(); \
|
|
+ preempt_enable_notrace(); \
|
|
}
|
|
|
|
#define this_cpu_add_4(pcp, val) arch_this_cpu_add(pcp, val, "laa", "asi", int)
|
|
@@ -95,14 +95,14 @@
|
|
typedef typeof(pcp) pcp_op_T__; \
|
|
pcp_op_T__ val__ = (val); \
|
|
pcp_op_T__ old__, *ptr__; \
|
|
- preempt_disable(); \
|
|
+ preempt_disable_notrace(); \
|
|
ptr__ = raw_cpu_ptr(&(pcp)); \
|
|
asm volatile( \
|
|
op " %[old__],%[val__],%[ptr__]\n" \
|
|
: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \
|
|
: [val__] "d" (val__) \
|
|
: "cc"); \
|
|
- preempt_enable(); \
|
|
+ preempt_enable_notrace(); \
|
|
old__ + val__; \
|
|
})
|
|
|
|
@@ -114,14 +114,14 @@
|
|
typedef typeof(pcp) pcp_op_T__; \
|
|
pcp_op_T__ val__ = (val); \
|
|
pcp_op_T__ old__, *ptr__; \
|
|
- preempt_disable(); \
|
|
+ preempt_disable_notrace(); \
|
|
ptr__ = raw_cpu_ptr(&(pcp)); \
|
|
asm volatile( \
|
|
op " %[old__],%[val__],%[ptr__]\n" \
|
|
: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \
|
|
: [val__] "d" (val__) \
|
|
: "cc"); \
|
|
- preempt_enable(); \
|
|
+ preempt_enable_notrace(); \
|
|
}
|
|
|
|
#define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, "lan")
|
|
@@ -136,10 +136,10 @@
|
|
typedef typeof(pcp) pcp_op_T__; \
|
|
pcp_op_T__ ret__; \
|
|
pcp_op_T__ *ptr__; \
|
|
- preempt_disable(); \
|
|
+ preempt_disable_notrace(); \
|
|
ptr__ = raw_cpu_ptr(&(pcp)); \
|
|
ret__ = cmpxchg(ptr__, oval, nval); \
|
|
- preempt_enable(); \
|
|
+ preempt_enable_notrace(); \
|
|
ret__; \
|
|
})
|
|
|
|
@@ -152,10 +152,10 @@
|
|
({ \
|
|
typeof(pcp) *ptr__; \
|
|
typeof(pcp) ret__; \
|
|
- preempt_disable(); \
|
|
+ preempt_disable_notrace(); \
|
|
ptr__ = raw_cpu_ptr(&(pcp)); \
|
|
ret__ = xchg(ptr__, nval); \
|
|
- preempt_enable(); \
|
|
+ preempt_enable_notrace(); \
|
|
ret__; \
|
|
})
|
|
|
|
@@ -171,11 +171,11 @@
|
|
typeof(pcp1) *p1__; \
|
|
typeof(pcp2) *p2__; \
|
|
int ret__; \
|
|
- preempt_disable(); \
|
|
+ preempt_disable_notrace(); \
|
|
p1__ = raw_cpu_ptr(&(pcp1)); \
|
|
p2__ = raw_cpu_ptr(&(pcp2)); \
|
|
ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__); \
|
|
- preempt_enable(); \
|
|
+ preempt_enable_notrace(); \
|
|
ret__; \
|
|
})
|
|
|
|
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
|
|
index 332eb35258676..902be2e6e96cf 100644
|
|
--- a/arch/x86/include/asm/ptrace.h
|
|
+++ b/arch/x86/include/asm/ptrace.h
|
|
@@ -309,8 +309,8 @@ static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
|
|
static const unsigned int argument_offs[] = {
|
|
#ifdef __i386__
|
|
offsetof(struct pt_regs, ax),
|
|
- offsetof(struct pt_regs, cx),
|
|
offsetof(struct pt_regs, dx),
|
|
+ offsetof(struct pt_regs, cx),
|
|
#define NR_REG_ARGUMENTS 3
|
|
#else
|
|
offsetof(struct pt_regs, di),
|
|
diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c
|
|
index abffa0be80da1..87282258d5bea 100644
|
|
--- a/arch/x86/mm/numa_emulation.c
|
|
+++ b/arch/x86/mm/numa_emulation.c
|
|
@@ -321,7 +321,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
|
|
u64 addr, u64 max_addr, u64 size)
|
|
{
|
|
return split_nodes_size_interleave_uniform(ei, pi, addr, max_addr, size,
|
|
- 0, NULL, NUMA_NO_NODE);
|
|
+ 0, NULL, 0);
|
|
}
|
|
|
|
int __init setup_emu2phys_nid(int *dfl_phys_nid)
|
|
diff --git a/block/blk-core.c b/block/blk-core.c
|
|
index d5e668ec751b5..ca6b677356864 100644
|
|
--- a/block/blk-core.c
|
|
+++ b/block/blk-core.c
|
|
@@ -502,6 +502,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
|
|
goto fail_stats;
|
|
|
|
q->backing_dev_info->ra_pages = VM_READAHEAD_PAGES;
|
|
+ q->backing_dev_info->io_pages = VM_READAHEAD_PAGES;
|
|
q->backing_dev_info->capabilities = BDI_CAP_CGROUP_WRITEBACK;
|
|
q->backing_dev_info->name = "block";
|
|
q->node = node_id;
|
|
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
|
|
index dcc6685d5becc..ef287c33d6d97 100644
|
|
--- a/block/blk-iocost.c
|
|
+++ b/block/blk-iocost.c
|
|
@@ -2074,14 +2074,15 @@ static void ioc_pd_free(struct blkg_policy_data *pd)
|
|
{
|
|
struct ioc_gq *iocg = pd_to_iocg(pd);
|
|
struct ioc *ioc = iocg->ioc;
|
|
+ unsigned long flags;
|
|
|
|
if (ioc) {
|
|
- spin_lock(&ioc->lock);
|
|
+ spin_lock_irqsave(&ioc->lock, flags);
|
|
if (!list_empty(&iocg->active_list)) {
|
|
propagate_active_weight(iocg, 0, 0);
|
|
list_del_init(&iocg->active_list);
|
|
}
|
|
- spin_unlock(&ioc->lock);
|
|
+ spin_unlock_irqrestore(&ioc->lock, flags);
|
|
|
|
hrtimer_cancel(&iocg->waitq_timer);
|
|
hrtimer_cancel(&iocg->delay_timer);
|
|
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
|
|
index 35f75c691d7cf..066b37963ad5f 100644
|
|
--- a/drivers/ata/libata-core.c
|
|
+++ b/drivers/ata/libata-core.c
|
|
@@ -4474,9 +4474,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
|
/* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
|
|
{ "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ, },
|
|
|
|
- /* Some Sandisk SSDs lock up hard with NCQ enabled. Reported on
|
|
- SD7SN6S256G and SD8SN8U256G */
|
|
- { "SanDisk SD[78]SN*G", NULL, ATA_HORKAGE_NONCQ, },
|
|
+ /* Sandisk SD7/8/9s lock up hard on large trims */
|
|
+ { "SanDisk SD[789]*", NULL, ATA_HORKAGE_MAX_TRIM_128M, },
|
|
|
|
/* devices which puke on READ_NATIVE_MAX */
|
|
{ "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, },
|
|
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
|
|
index 5596c9b6ebf23..464efedc778b0 100644
|
|
--- a/drivers/ata/libata-scsi.c
|
|
+++ b/drivers/ata/libata-scsi.c
|
|
@@ -2374,6 +2374,7 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
|
|
|
|
static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
|
|
{
|
|
+ struct ata_device *dev = args->dev;
|
|
u16 min_io_sectors;
|
|
|
|
rbuf[1] = 0xb0;
|
|
@@ -2399,7 +2400,12 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
|
|
* with the unmap bit set.
|
|
*/
|
|
if (ata_id_has_trim(args->id)) {
|
|
- put_unaligned_be64(65535 * ATA_MAX_TRIM_RNUM, &rbuf[36]);
|
|
+ u64 max_blocks = 65535 * ATA_MAX_TRIM_RNUM;
|
|
+
|
|
+ if (dev->horkage & ATA_HORKAGE_MAX_TRIM_128M)
|
|
+ max_blocks = 128 << (20 - SECTOR_SHIFT);
|
|
+
|
|
+ put_unaligned_be64(max_blocks, &rbuf[36]);
|
|
put_unaligned_be32(1, &rbuf[28]);
|
|
}
|
|
|
|
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
|
|
index 7b61d53ba050e..7c577cabb9c3b 100644
|
|
--- a/drivers/block/nbd.c
|
|
+++ b/drivers/block/nbd.c
|
|
@@ -1349,6 +1349,8 @@ static void nbd_set_cmd_timeout(struct nbd_device *nbd, u64 timeout)
|
|
nbd->tag_set.timeout = timeout * HZ;
|
|
if (timeout)
|
|
blk_queue_rq_timeout(nbd->disk->queue, timeout * HZ);
|
|
+ else
|
|
+ blk_queue_rq_timeout(nbd->disk->queue, 30 * HZ);
|
|
}
|
|
|
|
/* Must be called with config_lock held */
|
|
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
|
|
index 29d2d7a21bd7b..73f08cda21e0e 100644
|
|
--- a/drivers/cpuidle/cpuidle.c
|
|
+++ b/drivers/cpuidle/cpuidle.c
|
|
@@ -148,7 +148,8 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv,
|
|
*/
|
|
stop_critical_timings();
|
|
drv->states[index].enter_s2idle(dev, drv, index);
|
|
- WARN_ON(!irqs_disabled());
|
|
+ if (WARN_ON_ONCE(!irqs_disabled()))
|
|
+ local_irq_disable();
|
|
/*
|
|
* timekeeping_resume() that will be called by tick_unfreeze() for the
|
|
* first CPU executing it calls functions containing RCU read-side
|
|
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
|
|
index 672c73b4a2d4f..ff366c2f58c18 100644
|
|
--- a/drivers/dma/at_hdmac.c
|
|
+++ b/drivers/dma/at_hdmac.c
|
|
@@ -1667,6 +1667,8 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,
|
|
return NULL;
|
|
|
|
dmac_pdev = of_find_device_by_node(dma_spec->np);
|
|
+ if (!dmac_pdev)
|
|
+ return NULL;
|
|
|
|
dma_cap_zero(mask);
|
|
dma_cap_set(DMA_SLAVE, mask);
|
|
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
|
|
index ff392c01bad1f..7f9a86c3c58ff 100644
|
|
--- a/drivers/dma/dw-edma/dw-edma-core.c
|
|
+++ b/drivers/dma/dw-edma/dw-edma-core.c
|
|
@@ -391,7 +391,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
|
|
if (xfer->cyclic) {
|
|
burst->dar = xfer->xfer.cyclic.paddr;
|
|
} else {
|
|
- burst->dar = sg_dma_address(sg);
|
|
+ burst->dar = dst_addr;
|
|
/* Unlike the typical assumption by other
|
|
* drivers/IPs the peripheral memory isn't
|
|
* a FIFO memory, in this case, it's a
|
|
@@ -399,14 +399,13 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
|
|
* and destination addresses are increased
|
|
* by the same portion (data length)
|
|
*/
|
|
- src_addr += sg_dma_len(sg);
|
|
}
|
|
} else {
|
|
burst->dar = dst_addr;
|
|
if (xfer->cyclic) {
|
|
burst->sar = xfer->xfer.cyclic.paddr;
|
|
} else {
|
|
- burst->sar = sg_dma_address(sg);
|
|
+ burst->sar = src_addr;
|
|
/* Unlike the typical assumption by other
|
|
* drivers/IPs the peripheral memory isn't
|
|
* a FIFO memory, in this case, it's a
|
|
@@ -414,12 +413,14 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
|
|
* and destination addresses are increased
|
|
* by the same portion (data length)
|
|
*/
|
|
- dst_addr += sg_dma_len(sg);
|
|
}
|
|
}
|
|
|
|
- if (!xfer->cyclic)
|
|
+ if (!xfer->cyclic) {
|
|
+ src_addr += sg_dma_len(sg);
|
|
+ dst_addr += sg_dma_len(sg);
|
|
sg = sg_next(sg);
|
|
+ }
|
|
}
|
|
|
|
return vchan_tx_prep(&chan->vc, &desc->vd, xfer->flags);
|
|
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
|
|
index 56f18ae992332..308bed0a560ac 100644
|
|
--- a/drivers/dma/fsldma.h
|
|
+++ b/drivers/dma/fsldma.h
|
|
@@ -205,10 +205,10 @@ struct fsldma_chan {
|
|
#else
|
|
static u64 fsl_ioread64(const u64 __iomem *addr)
|
|
{
|
|
- u32 fsl_addr = lower_32_bits(addr);
|
|
- u64 fsl_addr_hi = (u64)in_le32((u32 *)(fsl_addr + 1)) << 32;
|
|
+ u32 val_lo = in_le32((u32 __iomem *)addr);
|
|
+ u32 val_hi = in_le32((u32 __iomem *)addr + 1);
|
|
|
|
- return fsl_addr_hi | in_le32((u32 *)fsl_addr);
|
|
+ return ((u64)val_hi << 32) + val_lo;
|
|
}
|
|
|
|
static void fsl_iowrite64(u64 val, u64 __iomem *addr)
|
|
@@ -219,10 +219,10 @@ static void fsl_iowrite64(u64 val, u64 __iomem *addr)
|
|
|
|
static u64 fsl_ioread64be(const u64 __iomem *addr)
|
|
{
|
|
- u32 fsl_addr = lower_32_bits(addr);
|
|
- u64 fsl_addr_hi = (u64)in_be32((u32 *)fsl_addr) << 32;
|
|
+ u32 val_hi = in_be32((u32 __iomem *)addr);
|
|
+ u32 val_lo = in_be32((u32 __iomem *)addr + 1);
|
|
|
|
- return fsl_addr_hi | in_be32((u32 *)(fsl_addr + 1));
|
|
+ return ((u64)val_hi << 32) + val_lo;
|
|
}
|
|
|
|
static void fsl_iowrite64be(u64 val, u64 __iomem *addr)
|
|
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c
|
|
index c2d779daa4b51..4bbf4172b9bf9 100644
|
|
--- a/drivers/dma/of-dma.c
|
|
+++ b/drivers/dma/of-dma.c
|
|
@@ -69,12 +69,12 @@ static struct dma_chan *of_dma_router_xlate(struct of_phandle_args *dma_spec,
|
|
return NULL;
|
|
|
|
chan = ofdma_target->of_dma_xlate(&dma_spec_target, ofdma_target);
|
|
- if (chan) {
|
|
- chan->router = ofdma->dma_router;
|
|
- chan->route_data = route_data;
|
|
- } else {
|
|
+ if (IS_ERR_OR_NULL(chan)) {
|
|
ofdma->dma_router->route_free(ofdma->dma_router->dev,
|
|
route_data);
|
|
+ } else {
|
|
+ chan->router = ofdma->dma_router;
|
|
+ chan->route_data = route_data;
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
|
index 6cce9ef61b294..cd81d10974a29 100644
|
|
--- a/drivers/dma/pl330.c
|
|
+++ b/drivers/dma/pl330.c
|
|
@@ -2788,6 +2788,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
|
|
while (burst != (1 << desc->rqcfg.brst_size))
|
|
desc->rqcfg.brst_size++;
|
|
|
|
+ desc->rqcfg.brst_len = get_burst_len(desc, len);
|
|
/*
|
|
* If burst size is smaller than bus width then make sure we only
|
|
* transfer one at a time to avoid a burst stradling an MFIFO entry.
|
|
@@ -2795,7 +2796,6 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
|
|
if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width)
|
|
desc->rqcfg.brst_len = 1;
|
|
|
|
- desc->rqcfg.brst_len = get_burst_len(desc, len);
|
|
desc->bytes_requested = len;
|
|
|
|
desc->txd.flags = flags;
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
index 247f53d41993d..60e50181f6d39 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
@@ -2043,12 +2043,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
|
|
&dm_atomic_state_funcs);
|
|
|
|
r = amdgpu_display_modeset_create_props(adev);
|
|
- if (r)
|
|
+ if (r) {
|
|
+ dc_release_state(state->context);
|
|
+ kfree(state);
|
|
return r;
|
|
+ }
|
|
|
|
r = amdgpu_dm_audio_init(adev);
|
|
- if (r)
|
|
+ if (r) {
|
|
+ dc_release_state(state->context);
|
|
+ kfree(state);
|
|
return r;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
@@ -2064,6 +2070,8 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
|
|
#if defined(CONFIG_ACPI)
|
|
struct amdgpu_dm_backlight_caps caps;
|
|
|
|
+ memset(&caps, 0, sizeof(caps));
|
|
+
|
|
if (dm->backlight_caps.caps_valid)
|
|
return;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
index 28a6c7b2ef4bb..2f858507ca702 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
@@ -101,7 +101,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
|
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
|
|
&operation_result);
|
|
|
|
- if (payload.write)
|
|
+ if (payload.write && result >= 0)
|
|
result = msg->size;
|
|
|
|
if (result < 0)
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
|
|
index 1599bb9711111..e860ae05feda1 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
|
|
@@ -1151,6 +1151,7 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont
|
|
bool video_large = false;
|
|
bool desktop_large = false;
|
|
bool dcc_disabled = false;
|
|
+ bool mpo_enabled = false;
|
|
|
|
for (i = 0; i < context->stream_count; i++) {
|
|
if (context->stream_status[i].plane_count == 0)
|
|
@@ -1159,6 +1160,9 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont
|
|
if (context->stream_status[i].plane_count > 2)
|
|
return DC_FAIL_UNSUPPORTED_1;
|
|
|
|
+ if (context->stream_status[i].plane_count > 1)
|
|
+ mpo_enabled = true;
|
|
+
|
|
for (j = 0; j < context->stream_status[i].plane_count; j++) {
|
|
struct dc_plane_state *plane =
|
|
context->stream_status[i].plane_states[j];
|
|
@@ -1182,6 +1186,10 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont
|
|
}
|
|
}
|
|
|
|
+ /* Disable MPO in multi-display configurations. */
|
|
+ if (context->stream_count > 1 && mpo_enabled)
|
|
+ return DC_FAIL_UNSUPPORTED_1;
|
|
+
|
|
/*
|
|
* Workaround: On DCN10 there is UMC issue that causes underflow when
|
|
* playing 4k video on 4k desktop with video downscaled and single channel
|
|
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
|
|
index 36a17caa3761d..e8d01abf27fa8 100644
|
|
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
|
|
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
|
|
@@ -375,8 +375,18 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
|
|
/* compare them in unit celsius degree */
|
|
if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
|
|
low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
|
|
- if (high > tdp_table->usSoftwareShutdownTemp)
|
|
- high = tdp_table->usSoftwareShutdownTemp;
|
|
+
|
|
+ /*
|
|
+ * As a common sense, usSoftwareShutdownTemp should be bigger
|
|
+ * than ThotspotLimit. For any invalid usSoftwareShutdownTemp,
|
|
+ * we will just use the max possible setting VEGA10_THERMAL_MAXIMUM_ALERT_TEMP
|
|
+ * to avoid false alarms.
|
|
+ */
|
|
+ if ((tdp_table->usSoftwareShutdownTemp >
|
|
+ range->hotspot_crit_max / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)) {
|
|
+ if (high > tdp_table->usSoftwareShutdownTemp)
|
|
+ high = tdp_table->usSoftwareShutdownTemp;
|
|
+ }
|
|
|
|
if (low > high)
|
|
return -EINVAL;
|
|
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
|
|
index 9ea748667fab0..40431a09dc97c 100644
|
|
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
|
|
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
|
|
@@ -199,12 +199,22 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
|
|
{
|
|
int ret;
|
|
u32 val;
|
|
+ u32 mask, reset_val;
|
|
+
|
|
+ val = gmu_read(gmu, REG_A6XX_GMU_CM3_DTCM_START + 0xff8);
|
|
+ if (val <= 0x20010004) {
|
|
+ mask = 0xffffffff;
|
|
+ reset_val = 0xbabeface;
|
|
+ } else {
|
|
+ mask = 0x1ff;
|
|
+ reset_val = 0x100;
|
|
+ }
|
|
|
|
gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
|
|
gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0);
|
|
|
|
ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val,
|
|
- val == 0xbabeface, 100, 10000);
|
|
+ (val & mask) == reset_val, 100, 10000);
|
|
|
|
if (ret)
|
|
DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
|
|
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
|
|
index 58d5acbcfc5c2..b984bafd27e25 100644
|
|
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
|
|
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
|
|
@@ -853,9 +853,9 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
|
|
crtc_state = drm_atomic_get_new_crtc_state(state->state,
|
|
state->crtc);
|
|
|
|
- min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxdwnscale);
|
|
+ min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxupscale);
|
|
ret = drm_atomic_helper_check_plane_state(state, crtc_state, min_scale,
|
|
- pdpu->pipe_sblk->maxupscale << 16,
|
|
+ pdpu->pipe_sblk->maxdwnscale << 16,
|
|
true, true);
|
|
if (ret) {
|
|
DPU_ERROR_PLANE(pdpu, "Check plane state failed (%d)\n", ret);
|
|
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
|
|
index 5ccfad794c6a5..561bfa48841c3 100644
|
|
--- a/drivers/gpu/drm/msm/msm_atomic.c
|
|
+++ b/drivers/gpu/drm/msm/msm_atomic.c
|
|
@@ -27,6 +27,34 @@ int msm_atomic_prepare_fb(struct drm_plane *plane,
|
|
return msm_framebuffer_prepare(new_state->fb, kms->aspace);
|
|
}
|
|
|
|
+/*
|
|
+ * Helpers to control vblanks while we flush.. basically just to ensure
|
|
+ * that vblank accounting is switched on, so we get valid seqn/timestamp
|
|
+ * on pageflip events (if requested)
|
|
+ */
|
|
+
|
|
+static void vblank_get(struct msm_kms *kms, unsigned crtc_mask)
|
|
+{
|
|
+ struct drm_crtc *crtc;
|
|
+
|
|
+ for_each_crtc_mask(kms->dev, crtc, crtc_mask) {
|
|
+ if (!crtc->state->active)
|
|
+ continue;
|
|
+ drm_crtc_vblank_get(crtc);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void vblank_put(struct msm_kms *kms, unsigned crtc_mask)
|
|
+{
|
|
+ struct drm_crtc *crtc;
|
|
+
|
|
+ for_each_crtc_mask(kms->dev, crtc, crtc_mask) {
|
|
+ if (!crtc->state->active)
|
|
+ continue;
|
|
+ drm_crtc_vblank_put(crtc);
|
|
+ }
|
|
+}
|
|
+
|
|
static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx)
|
|
{
|
|
unsigned crtc_mask = BIT(crtc_idx);
|
|
@@ -44,6 +72,8 @@ static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx)
|
|
|
|
kms->funcs->enable_commit(kms);
|
|
|
|
+ vblank_get(kms, crtc_mask);
|
|
+
|
|
/*
|
|
* Flush hardware updates:
|
|
*/
|
|
@@ -58,6 +88,8 @@ static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx)
|
|
kms->funcs->wait_flush(kms, crtc_mask);
|
|
trace_msm_atomic_wait_flush_finish(crtc_mask);
|
|
|
|
+ vblank_put(kms, crtc_mask);
|
|
+
|
|
mutex_lock(&kms->commit_lock);
|
|
kms->funcs->complete_commit(kms, crtc_mask);
|
|
mutex_unlock(&kms->commit_lock);
|
|
@@ -221,6 +253,8 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)
|
|
*/
|
|
kms->pending_crtc_mask &= ~crtc_mask;
|
|
|
|
+ vblank_get(kms, crtc_mask);
|
|
+
|
|
/*
|
|
* Flush hardware updates:
|
|
*/
|
|
@@ -235,6 +269,8 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)
|
|
kms->funcs->wait_flush(kms, crtc_mask);
|
|
trace_msm_atomic_wait_flush_finish(crtc_mask);
|
|
|
|
+ vblank_put(kms, crtc_mask);
|
|
+
|
|
mutex_lock(&kms->commit_lock);
|
|
kms->funcs->complete_commit(kms, crtc_mask);
|
|
mutex_unlock(&kms->commit_lock);
|
|
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
|
|
index b73fbb65e14b2..4558d66761b3c 100644
|
|
--- a/drivers/gpu/drm/msm/msm_drv.c
|
|
+++ b/drivers/gpu/drm/msm/msm_drv.c
|
|
@@ -1321,6 +1321,13 @@ static int msm_pdev_remove(struct platform_device *pdev)
|
|
return 0;
|
|
}
|
|
|
|
+static void msm_pdev_shutdown(struct platform_device *pdev)
|
|
+{
|
|
+ struct drm_device *drm = platform_get_drvdata(pdev);
|
|
+
|
|
+ drm_atomic_helper_shutdown(drm);
|
|
+}
|
|
+
|
|
static const struct of_device_id dt_match[] = {
|
|
{ .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 },
|
|
{ .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 },
|
|
@@ -1332,6 +1339,7 @@ MODULE_DEVICE_TABLE(of, dt_match);
|
|
static struct platform_driver msm_platform_driver = {
|
|
.probe = msm_pdev_probe,
|
|
.remove = msm_pdev_remove,
|
|
+ .shutdown = msm_pdev_shutdown,
|
|
.driver = {
|
|
.name = "msm",
|
|
.of_match_table = dt_match,
|
|
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
|
|
index 3c5ddbf30e974..f5e18802e7bc6 100644
|
|
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
|
|
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
|
|
@@ -451,11 +451,12 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
|
|
if (omap_state->manually_updated)
|
|
return;
|
|
|
|
- spin_lock_irq(&crtc->dev->event_lock);
|
|
drm_crtc_vblank_on(crtc);
|
|
+
|
|
ret = drm_crtc_vblank_get(crtc);
|
|
WARN_ON(ret != 0);
|
|
|
|
+ spin_lock_irq(&crtc->dev->event_lock);
|
|
omap_crtc_arm_event(crtc);
|
|
spin_unlock_irq(&crtc->dev->event_lock);
|
|
}
|
|
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
|
index 09df5ecc2c79b..fbc93d8dda5ed 100644
|
|
--- a/drivers/hid/hid-ids.h
|
|
+++ b/drivers/hid/hid-ids.h
|
|
@@ -730,6 +730,9 @@
|
|
#define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3
|
|
#define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5
|
|
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d
|
|
+#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019
|
|
+#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E 0x602e
|
|
+#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093 0x6093
|
|
|
|
#define USB_VENDOR_ID_LG 0x1fd2
|
|
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
|
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
|
|
index b3dd60897ffda..8a739ec50cc00 100644
|
|
--- a/drivers/hid/hid-quirks.c
|
|
+++ b/drivers/hid/hid-quirks.c
|
|
@@ -105,6 +105,9 @@ static const struct hid_device_id hid_quirks[] = {
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E), HID_QUIRK_ALWAYS_POLL },
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093), HID_QUIRK_ALWAYS_POLL },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET },
|
|
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
|
index 183ff3d251299..006bc07bcd301 100644
|
|
--- a/drivers/hwmon/applesmc.c
|
|
+++ b/drivers/hwmon/applesmc.c
|
|
@@ -748,15 +748,18 @@ static ssize_t applesmc_light_show(struct device *dev,
|
|
}
|
|
|
|
ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
|
|
+ if (ret)
|
|
+ goto out;
|
|
/* newer macbooks report a single 10-bit bigendian value */
|
|
if (data_length == 10) {
|
|
left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
|
|
goto out;
|
|
}
|
|
left = buffer[2];
|
|
+
|
|
+ ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
|
|
if (ret)
|
|
goto out;
|
|
- ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
|
|
right = buffer[2];
|
|
|
|
out:
|
|
@@ -805,12 +808,11 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
|
|
to_index(attr));
|
|
|
|
ret = applesmc_read_key(newkey, buffer, 2);
|
|
- speed = ((buffer[0] << 8 | buffer[1]) >> 2);
|
|
-
|
|
if (ret)
|
|
return ret;
|
|
- else
|
|
- return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
|
|
+
|
|
+ speed = ((buffer[0] << 8 | buffer[1]) >> 2);
|
|
+ return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
|
|
}
|
|
|
|
static ssize_t applesmc_store_fan_speed(struct device *dev,
|
|
@@ -846,12 +848,11 @@ static ssize_t applesmc_show_fan_manual(struct device *dev,
|
|
u8 buffer[2];
|
|
|
|
ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
|
|
- manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
|
|
-
|
|
if (ret)
|
|
return ret;
|
|
- else
|
|
- return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
|
|
+
|
|
+ manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
|
|
+ return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
|
|
}
|
|
|
|
static ssize_t applesmc_store_fan_manual(struct device *dev,
|
|
@@ -867,10 +868,11 @@ static ssize_t applesmc_store_fan_manual(struct device *dev,
|
|
return -EINVAL;
|
|
|
|
ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
|
|
- val = (buffer[0] << 8 | buffer[1]);
|
|
if (ret)
|
|
goto out;
|
|
|
|
+ val = (buffer[0] << 8 | buffer[1]);
|
|
+
|
|
if (input)
|
|
val = val | (0x01 << to_index(attr));
|
|
else
|
|
@@ -946,13 +948,12 @@ static ssize_t applesmc_key_count_show(struct device *dev,
|
|
u32 count;
|
|
|
|
ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
|
|
- count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
|
|
- ((u32)buffer[2]<<8) + buffer[3];
|
|
-
|
|
if (ret)
|
|
return ret;
|
|
- else
|
|
- return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
|
|
+
|
|
+ count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
|
|
+ ((u32)buffer[2]<<8) + buffer[3];
|
|
+ return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
|
|
}
|
|
|
|
static ssize_t applesmc_key_at_index_read_show(struct device *dev,
|
|
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
|
|
index 3a7094f4813f2..cdafc652d9d1a 100644
|
|
--- a/drivers/iommu/amd_iommu.c
|
|
+++ b/drivers/iommu/amd_iommu.c
|
|
@@ -4431,6 +4431,7 @@ int amd_iommu_deactivate_guest_mode(void *data)
|
|
struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
|
|
struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
|
|
struct irq_cfg *cfg = ir_data->cfg;
|
|
+ u64 valid = entry->lo.fields_remap.valid;
|
|
|
|
if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
|
|
!entry || !entry->lo.fields_vapic.guest_mode)
|
|
@@ -4439,6 +4440,7 @@ int amd_iommu_deactivate_guest_mode(void *data)
|
|
entry->lo.val = 0;
|
|
entry->hi.val = 0;
|
|
|
|
+ entry->lo.fields_remap.valid = valid;
|
|
entry->lo.fields_remap.dm = apic->irq_dest_mode;
|
|
entry->lo.fields_remap.int_type = apic->irq_delivery_mode;
|
|
entry->hi.fields.vector = cfg->vector;
|
|
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
|
|
index cdc1f4736a116..2ffec65df3889 100644
|
|
--- a/drivers/iommu/intel-iommu.c
|
|
+++ b/drivers/iommu/intel-iommu.c
|
|
@@ -123,29 +123,29 @@ static inline unsigned int level_to_offset_bits(int level)
|
|
return (level - 1) * LEVEL_STRIDE;
|
|
}
|
|
|
|
-static inline int pfn_level_offset(unsigned long pfn, int level)
|
|
+static inline int pfn_level_offset(u64 pfn, int level)
|
|
{
|
|
return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
|
|
}
|
|
|
|
-static inline unsigned long level_mask(int level)
|
|
+static inline u64 level_mask(int level)
|
|
{
|
|
- return -1UL << level_to_offset_bits(level);
|
|
+ return -1ULL << level_to_offset_bits(level);
|
|
}
|
|
|
|
-static inline unsigned long level_size(int level)
|
|
+static inline u64 level_size(int level)
|
|
{
|
|
- return 1UL << level_to_offset_bits(level);
|
|
+ return 1ULL << level_to_offset_bits(level);
|
|
}
|
|
|
|
-static inline unsigned long align_to_level(unsigned long pfn, int level)
|
|
+static inline u64 align_to_level(u64 pfn, int level)
|
|
{
|
|
return (pfn + level_size(level) - 1) & level_mask(level);
|
|
}
|
|
|
|
static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
|
|
{
|
|
- return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
|
|
+ return 1UL << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
|
|
}
|
|
|
|
/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
|
|
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
|
|
index 6bfb283e6f287..f697f3a1d46bc 100644
|
|
--- a/drivers/iommu/intel_irq_remapping.c
|
|
+++ b/drivers/iommu/intel_irq_remapping.c
|
|
@@ -507,12 +507,18 @@ static void iommu_enable_irq_remapping(struct intel_iommu *iommu)
|
|
|
|
/* Enable interrupt-remapping */
|
|
iommu->gcmd |= DMA_GCMD_IRE;
|
|
- iommu->gcmd &= ~DMA_GCMD_CFI; /* Block compatibility-format MSIs */
|
|
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
|
|
-
|
|
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
|
|
readl, (sts & DMA_GSTS_IRES), sts);
|
|
|
|
+ /* Block compatibility-format MSIs */
|
|
+ if (sts & DMA_GSTS_CFIS) {
|
|
+ iommu->gcmd &= ~DMA_GCMD_CFI;
|
|
+ writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
|
|
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
|
|
+ readl, !(sts & DMA_GSTS_CFIS), sts);
|
|
+ }
|
|
+
|
|
/*
|
|
* With CFI clear in the Global Command register, we should be
|
|
* protected from dangerous (i.e. compatibility) interrupts
|
|
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
|
|
index 151aa95775be2..af6d4f898e4c1 100644
|
|
--- a/drivers/md/dm-cache-metadata.c
|
|
+++ b/drivers/md/dm-cache-metadata.c
|
|
@@ -537,12 +537,16 @@ static int __create_persistent_data_objects(struct dm_cache_metadata *cmd,
|
|
CACHE_MAX_CONCURRENT_LOCKS);
|
|
if (IS_ERR(cmd->bm)) {
|
|
DMERR("could not create block manager");
|
|
- return PTR_ERR(cmd->bm);
|
|
+ r = PTR_ERR(cmd->bm);
|
|
+ cmd->bm = NULL;
|
|
+ return r;
|
|
}
|
|
|
|
r = __open_or_format_metadata(cmd, may_format_device);
|
|
- if (r)
|
|
+ if (r) {
|
|
dm_block_manager_destroy(cmd->bm);
|
|
+ cmd->bm = NULL;
|
|
+ }
|
|
|
|
return r;
|
|
}
|
|
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
|
|
index ffbda729e26e9..1af82fbbac0c4 100644
|
|
--- a/drivers/md/dm-crypt.c
|
|
+++ b/drivers/md/dm-crypt.c
|
|
@@ -720,7 +720,7 @@ static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
|
|
u8 buf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(__le64));
|
|
struct skcipher_request *req;
|
|
struct scatterlist src, dst;
|
|
- struct crypto_wait wait;
|
|
+ DECLARE_CRYPTO_WAIT(wait);
|
|
int err;
|
|
|
|
req = skcipher_request_alloc(any_tfm(cc), GFP_NOIO);
|
|
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
|
|
index 1f63084ef3291..d6edfe84e7490 100644
|
|
--- a/drivers/md/dm-integrity.c
|
|
+++ b/drivers/md/dm-integrity.c
|
|
@@ -2365,6 +2365,7 @@ next_chunk:
|
|
range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);
|
|
if (unlikely(range.logical_sector >= ic->provided_data_sectors)) {
|
|
if (ic->mode == 'B') {
|
|
+ block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
|
|
DEBUG_print("queue_delayed_work: bitmap_flush_work\n");
|
|
queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, 0);
|
|
}
|
|
@@ -2442,6 +2443,17 @@ next_chunk:
|
|
goto err;
|
|
}
|
|
|
|
+ if (ic->mode == 'B') {
|
|
+ sector_t start, end;
|
|
+ start = (range.logical_sector >>
|
|
+ (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit)) <<
|
|
+ (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
|
|
+ end = ((range.logical_sector + range.n_sectors) >>
|
|
+ (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit)) <<
|
|
+ (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
|
|
+ block_bitmap_op(ic, ic->recalc_bitmap, start, end - start, BITMAP_OP_CLEAR);
|
|
+ }
|
|
+
|
|
advance_and_next:
|
|
cond_resched();
|
|
|
|
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
|
|
index f2de4c73cc8fa..54ecfea2cf47b 100644
|
|
--- a/drivers/md/dm-mpath.c
|
|
+++ b/drivers/md/dm-mpath.c
|
|
@@ -1190,17 +1190,25 @@ static void multipath_wait_for_pg_init_completion(struct multipath *m)
|
|
static void flush_multipath_work(struct multipath *m)
|
|
{
|
|
if (m->hw_handler_name) {
|
|
- set_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
|
|
- smp_mb__after_atomic();
|
|
+ unsigned long flags;
|
|
+
|
|
+ if (!atomic_read(&m->pg_init_in_progress))
|
|
+ goto skip;
|
|
+
|
|
+ spin_lock_irqsave(&m->lock, flags);
|
|
+ if (atomic_read(&m->pg_init_in_progress) &&
|
|
+ !test_and_set_bit(MPATHF_PG_INIT_DISABLED, &m->flags)) {
|
|
+ spin_unlock_irqrestore(&m->lock, flags);
|
|
|
|
- if (atomic_read(&m->pg_init_in_progress))
|
|
flush_workqueue(kmpath_handlerd);
|
|
- multipath_wait_for_pg_init_completion(m);
|
|
+ multipath_wait_for_pg_init_completion(m);
|
|
|
|
- clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
|
|
- smp_mb__after_atomic();
|
|
+ spin_lock_irqsave(&m->lock, flags);
|
|
+ clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
|
|
+ }
|
|
+ spin_unlock_irqrestore(&m->lock, flags);
|
|
}
|
|
-
|
|
+skip:
|
|
if (m->queue_mode == DM_TYPE_BIO_BASED)
|
|
flush_work(&m->process_queued_bios);
|
|
flush_work(&m->trigger_event);
|
|
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
|
|
index 4cd8868f80040..a5ed59eafdc51 100644
|
|
--- a/drivers/md/dm-thin-metadata.c
|
|
+++ b/drivers/md/dm-thin-metadata.c
|
|
@@ -739,12 +739,16 @@ static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool f
|
|
THIN_MAX_CONCURRENT_LOCKS);
|
|
if (IS_ERR(pmd->bm)) {
|
|
DMERR("could not create block manager");
|
|
- return PTR_ERR(pmd->bm);
|
|
+ r = PTR_ERR(pmd->bm);
|
|
+ pmd->bm = NULL;
|
|
+ return r;
|
|
}
|
|
|
|
r = __open_or_format_metadata(pmd, format_device);
|
|
- if (r)
|
|
+ if (r) {
|
|
dm_block_manager_destroy(pmd->bm);
|
|
+ pmd->bm = NULL;
|
|
+ }
|
|
|
|
return r;
|
|
}
|
|
@@ -954,7 +958,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
|
|
}
|
|
|
|
pmd_write_lock_in_core(pmd);
|
|
- if (!dm_bm_is_read_only(pmd->bm) && !pmd->fail_io) {
|
|
+ if (!pmd->fail_io && !dm_bm_is_read_only(pmd->bm)) {
|
|
r = __commit_transaction(pmd);
|
|
if (r < 0)
|
|
DMWARN("%s: __commit_transaction() failed, error = %d",
|
|
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
|
|
index ed2f711c24c48..4e414b06192eb 100644
|
|
--- a/drivers/md/dm-writecache.c
|
|
+++ b/drivers/md/dm-writecache.c
|
|
@@ -224,6 +224,7 @@ static int persistent_memory_claim(struct dm_writecache *wc)
|
|
pfn_t pfn;
|
|
int id;
|
|
struct page **pages;
|
|
+ sector_t offset;
|
|
|
|
wc->memory_vmapped = false;
|
|
|
|
@@ -242,9 +243,16 @@ static int persistent_memory_claim(struct dm_writecache *wc)
|
|
goto err1;
|
|
}
|
|
|
|
+ offset = get_start_sect(wc->ssd_dev->bdev);
|
|
+ if (offset & (PAGE_SIZE / 512 - 1)) {
|
|
+ r = -EINVAL;
|
|
+ goto err1;
|
|
+ }
|
|
+ offset >>= PAGE_SHIFT - 9;
|
|
+
|
|
id = dax_read_lock();
|
|
|
|
- da = dax_direct_access(wc->ssd_dev->dax_dev, 0, p, &wc->memory_map, &pfn);
|
|
+ da = dax_direct_access(wc->ssd_dev->dax_dev, offset, p, &wc->memory_map, &pfn);
|
|
if (da < 0) {
|
|
wc->memory_map = NULL;
|
|
r = da;
|
|
@@ -266,7 +274,7 @@ static int persistent_memory_claim(struct dm_writecache *wc)
|
|
i = 0;
|
|
do {
|
|
long daa;
|
|
- daa = dax_direct_access(wc->ssd_dev->dax_dev, i, p - i,
|
|
+ daa = dax_direct_access(wc->ssd_dev->dax_dev, offset + i, p - i,
|
|
NULL, &pfn);
|
|
if (daa <= 0) {
|
|
r = daa ? daa : -EINVAL;
|
|
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
|
|
index 749ec268d957d..54c089a50b152 100644
|
|
--- a/drivers/md/persistent-data/dm-block-manager.c
|
|
+++ b/drivers/md/persistent-data/dm-block-manager.c
|
|
@@ -493,7 +493,7 @@ int dm_bm_write_lock(struct dm_block_manager *bm,
|
|
void *p;
|
|
int r;
|
|
|
|
- if (bm->read_only)
|
|
+ if (dm_bm_is_read_only(bm))
|
|
return -EPERM;
|
|
|
|
p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result);
|
|
@@ -562,7 +562,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm,
|
|
struct buffer_aux *aux;
|
|
void *p;
|
|
|
|
- if (bm->read_only)
|
|
+ if (dm_bm_is_read_only(bm))
|
|
return -EPERM;
|
|
|
|
p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result);
|
|
@@ -602,7 +602,7 @@ EXPORT_SYMBOL_GPL(dm_bm_unlock);
|
|
|
|
int dm_bm_flush(struct dm_block_manager *bm)
|
|
{
|
|
- if (bm->read_only)
|
|
+ if (dm_bm_is_read_only(bm))
|
|
return -EPERM;
|
|
|
|
return dm_bufio_write_dirty_buffers(bm->bufio);
|
|
@@ -616,19 +616,21 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b)
|
|
|
|
bool dm_bm_is_read_only(struct dm_block_manager *bm)
|
|
{
|
|
- return bm->read_only;
|
|
+ return (bm ? bm->read_only : true);
|
|
}
|
|
EXPORT_SYMBOL_GPL(dm_bm_is_read_only);
|
|
|
|
void dm_bm_set_read_only(struct dm_block_manager *bm)
|
|
{
|
|
- bm->read_only = true;
|
|
+ if (bm)
|
|
+ bm->read_only = true;
|
|
}
|
|
EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
|
|
|
|
void dm_bm_set_read_write(struct dm_block_manager *bm)
|
|
{
|
|
- bm->read_only = false;
|
|
+ if (bm)
|
|
+ bm->read_only = false;
|
|
}
|
|
EXPORT_SYMBOL_GPL(dm_bm_set_read_write);
|
|
|
|
diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c
|
|
index 84ec36156f73f..c77281d43f892 100644
|
|
--- a/drivers/media/platform/vicodec/vicodec-core.c
|
|
+++ b/drivers/media/platform/vicodec/vicodec-core.c
|
|
@@ -2052,6 +2052,7 @@ static int vicodec_request_validate(struct media_request *req)
|
|
}
|
|
ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
|
|
vicodec_ctrl_stateless_state.id);
|
|
+ v4l2_ctrl_request_hdl_put(hdl);
|
|
if (!ctrl) {
|
|
v4l2_info(&ctx->dev->v4l2_dev,
|
|
"Missing required codec control\n");
|
|
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
|
|
index 6f80c251f6413..e84f9dccf448a 100644
|
|
--- a/drivers/media/rc/rc-main.c
|
|
+++ b/drivers/media/rc/rc-main.c
|
|
@@ -1256,6 +1256,10 @@ static ssize_t store_protocols(struct device *device,
|
|
}
|
|
|
|
mutex_lock(&dev->lock);
|
|
+ if (!dev->registered) {
|
|
+ mutex_unlock(&dev->lock);
|
|
+ return -ENODEV;
|
|
+ }
|
|
|
|
old_protocols = *current_protocols;
|
|
new_protocols = old_protocols;
|
|
@@ -1394,6 +1398,10 @@ static ssize_t store_filter(struct device *device,
|
|
return -EINVAL;
|
|
|
|
mutex_lock(&dev->lock);
|
|
+ if (!dev->registered) {
|
|
+ mutex_unlock(&dev->lock);
|
|
+ return -ENODEV;
|
|
+ }
|
|
|
|
new_filter = *filter;
|
|
if (fattr->mask)
|
|
@@ -1508,6 +1516,10 @@ static ssize_t store_wakeup_protocols(struct device *device,
|
|
int i;
|
|
|
|
mutex_lock(&dev->lock);
|
|
+ if (!dev->registered) {
|
|
+ mutex_unlock(&dev->lock);
|
|
+ return -ENODEV;
|
|
+ }
|
|
|
|
allowed = dev->allowed_wakeup_protocols;
|
|
|
|
@@ -1565,25 +1577,25 @@ static void rc_dev_release(struct device *device)
|
|
kfree(dev);
|
|
}
|
|
|
|
-#define ADD_HOTPLUG_VAR(fmt, val...) \
|
|
- do { \
|
|
- int err = add_uevent_var(env, fmt, val); \
|
|
- if (err) \
|
|
- return err; \
|
|
- } while (0)
|
|
-
|
|
static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
|
{
|
|
struct rc_dev *dev = to_rc_dev(device);
|
|
+ int ret = 0;
|
|
|
|
- if (dev->rc_map.name)
|
|
- ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
|
|
- if (dev->driver_name)
|
|
- ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name);
|
|
- if (dev->device_name)
|
|
- ADD_HOTPLUG_VAR("DEV_NAME=%s", dev->device_name);
|
|
+ mutex_lock(&dev->lock);
|
|
|
|
- return 0;
|
|
+ if (!dev->registered)
|
|
+ ret = -ENODEV;
|
|
+ if (ret == 0 && dev->rc_map.name)
|
|
+ ret = add_uevent_var(env, "NAME=%s", dev->rc_map.name);
|
|
+ if (ret == 0 && dev->driver_name)
|
|
+ ret = add_uevent_var(env, "DRV_NAME=%s", dev->driver_name);
|
|
+ if (ret == 0 && dev->device_name)
|
|
+ ret = add_uevent_var(env, "DEV_NAME=%s", dev->device_name);
|
|
+
|
|
+ mutex_unlock(&dev->lock);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
/*
|
|
@@ -1975,14 +1987,14 @@ void rc_unregister_device(struct rc_dev *dev)
|
|
del_timer_sync(&dev->timer_keyup);
|
|
del_timer_sync(&dev->timer_repeat);
|
|
|
|
- rc_free_rx_device(dev);
|
|
-
|
|
mutex_lock(&dev->lock);
|
|
if (dev->users && dev->close)
|
|
dev->close(dev);
|
|
dev->registered = false;
|
|
mutex_unlock(&dev->lock);
|
|
|
|
+ rc_free_rx_device(dev);
|
|
+
|
|
/*
|
|
* lirc device should be freed with dev->registered = false, so
|
|
* that userspace polling will get notified.
|
|
diff --git a/drivers/misc/habanalabs/firmware_if.c b/drivers/misc/habanalabs/firmware_if.c
|
|
index ea2ca67fbfbfa..153858475abc1 100644
|
|
--- a/drivers/misc/habanalabs/firmware_if.c
|
|
+++ b/drivers/misc/habanalabs/firmware_if.c
|
|
@@ -11,6 +11,7 @@
|
|
#include <linux/genalloc.h>
|
|
#include <linux/io-64-nonatomic-lo-hi.h>
|
|
|
|
+#define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */
|
|
/**
|
|
* hl_fw_push_fw_to_device() - Push FW code to device.
|
|
* @hdev: pointer to hl_device structure.
|
|
@@ -43,6 +44,14 @@ int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
|
|
|
|
dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size);
|
|
|
|
+ if (fw_size > FW_FILE_MAX_SIZE) {
|
|
+ dev_err(hdev->dev,
|
|
+ "FW file size %zu exceeds maximum of %u bytes\n",
|
|
+ fw_size, FW_FILE_MAX_SIZE);
|
|
+ rc = -EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
fw_data = (const u64 *) fw->data;
|
|
|
|
memcpy_toio(dst, fw_data, fw_size);
|
|
diff --git a/drivers/misc/habanalabs/memory.c b/drivers/misc/habanalabs/memory.c
|
|
index 22566b75ca50c..acfccf32be6b9 100644
|
|
--- a/drivers/misc/habanalabs/memory.c
|
|
+++ b/drivers/misc/habanalabs/memory.c
|
|
@@ -67,6 +67,11 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
|
|
num_pgs = (args->alloc.mem_size + (page_size - 1)) >> page_shift;
|
|
total_size = num_pgs << page_shift;
|
|
|
|
+ if (!total_size) {
|
|
+ dev_err(hdev->dev, "Cannot allocate 0 bytes\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
contiguous = args->flags & HL_MEM_CONTIGUOUS;
|
|
|
|
if (contiguous) {
|
|
@@ -94,7 +99,7 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
|
|
phys_pg_pack->contiguous = contiguous;
|
|
|
|
phys_pg_pack->pages = kvmalloc_array(num_pgs, sizeof(u64), GFP_KERNEL);
|
|
- if (!phys_pg_pack->pages) {
|
|
+ if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
|
|
rc = -ENOMEM;
|
|
goto pages_arr_err;
|
|
}
|
|
@@ -689,7 +694,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
|
|
|
|
phys_pg_pack->pages = kvmalloc_array(total_npages, sizeof(u64),
|
|
GFP_KERNEL);
|
|
- if (!phys_pg_pack->pages) {
|
|
+ if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
|
|
rc = -ENOMEM;
|
|
goto page_pack_arr_mem_err;
|
|
}
|
|
diff --git a/drivers/misc/habanalabs/mmu.c b/drivers/misc/habanalabs/mmu.c
|
|
index 176c315836f12..d66e16de4cda3 100644
|
|
--- a/drivers/misc/habanalabs/mmu.c
|
|
+++ b/drivers/misc/habanalabs/mmu.c
|
|
@@ -422,7 +422,7 @@ int hl_mmu_init(struct hl_device *hdev)
|
|
hdev->mmu_shadow_hop0 = kvmalloc_array(prop->max_asid,
|
|
prop->mmu_hop_table_size,
|
|
GFP_KERNEL | __GFP_ZERO);
|
|
- if (!hdev->mmu_shadow_hop0) {
|
|
+ if (ZERO_OR_NULL_PTR(hdev->mmu_shadow_hop0)) {
|
|
rc = -ENOMEM;
|
|
goto err_pool_add;
|
|
}
|
|
diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c
|
|
index c19f4c3f115a4..2d65b32d205a5 100644
|
|
--- a/drivers/mmc/host/cqhci.c
|
|
+++ b/drivers/mmc/host/cqhci.c
|
|
@@ -299,16 +299,16 @@ static void __cqhci_disable(struct cqhci_host *cq_host)
|
|
cq_host->activated = false;
|
|
}
|
|
|
|
-int cqhci_suspend(struct mmc_host *mmc)
|
|
+int cqhci_deactivate(struct mmc_host *mmc)
|
|
{
|
|
struct cqhci_host *cq_host = mmc->cqe_private;
|
|
|
|
- if (cq_host->enabled)
|
|
+ if (cq_host->enabled && cq_host->activated)
|
|
__cqhci_disable(cq_host);
|
|
|
|
return 0;
|
|
}
|
|
-EXPORT_SYMBOL(cqhci_suspend);
|
|
+EXPORT_SYMBOL(cqhci_deactivate);
|
|
|
|
int cqhci_resume(struct mmc_host *mmc)
|
|
{
|
|
diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
|
|
index def76e9b5cacf..437700179de4d 100644
|
|
--- a/drivers/mmc/host/cqhci.h
|
|
+++ b/drivers/mmc/host/cqhci.h
|
|
@@ -230,7 +230,11 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error,
|
|
int data_error);
|
|
int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, bool dma64);
|
|
struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev);
|
|
-int cqhci_suspend(struct mmc_host *mmc);
|
|
+int cqhci_deactivate(struct mmc_host *mmc);
|
|
+static inline int cqhci_suspend(struct mmc_host *mmc)
|
|
+{
|
|
+ return cqhci_deactivate(mmc);
|
|
+}
|
|
int cqhci_resume(struct mmc_host *mmc);
|
|
|
|
#endif
|
|
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
|
|
index 010fe29a48883..9d47a2bd2546b 100644
|
|
--- a/drivers/mmc/host/mtk-sd.c
|
|
+++ b/drivers/mmc/host/mtk-sd.c
|
|
@@ -22,6 +22,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/interrupt.h>
|
|
+#include <linux/reset.h>
|
|
|
|
#include <linux/mmc/card.h>
|
|
#include <linux/mmc/core.h>
|
|
@@ -412,6 +413,7 @@ struct msdc_host {
|
|
struct pinctrl_state *pins_uhs;
|
|
struct delayed_work req_timeout;
|
|
int irq; /* host interrupt */
|
|
+ struct reset_control *reset;
|
|
|
|
struct clk *src_clk; /* msdc source clock */
|
|
struct clk *h_clk; /* msdc h_clk */
|
|
@@ -1474,6 +1476,12 @@ static void msdc_init_hw(struct msdc_host *host)
|
|
u32 val;
|
|
u32 tune_reg = host->dev_comp->pad_tune_reg;
|
|
|
|
+ if (host->reset) {
|
|
+ reset_control_assert(host->reset);
|
|
+ usleep_range(10, 50);
|
|
+ reset_control_deassert(host->reset);
|
|
+ }
|
|
+
|
|
/* Configure to MMC/SD mode, clock free running */
|
|
sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN);
|
|
|
|
@@ -2232,6 +2240,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
|
|
if (IS_ERR(host->src_clk_cg))
|
|
host->src_clk_cg = NULL;
|
|
|
|
+ host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
|
|
+ "hrst");
|
|
+ if (IS_ERR(host->reset))
|
|
+ return PTR_ERR(host->reset);
|
|
+
|
|
host->irq = platform_get_irq(pdev, 0);
|
|
if (host->irq < 0) {
|
|
ret = -EINVAL;
|
|
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
|
|
index 01fc437ed9659..5581a5c86fce3 100644
|
|
--- a/drivers/mmc/host/sdhci-acpi.c
|
|
+++ b/drivers/mmc/host/sdhci-acpi.c
|
|
@@ -532,6 +532,11 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd = {
|
|
.caps = MMC_CAP_NONREMOVABLE,
|
|
};
|
|
|
|
+struct amd_sdhci_host {
|
|
+ bool tuned_clock;
|
|
+ bool dll_enabled;
|
|
+};
|
|
+
|
|
/* AMD sdhci reset dll register. */
|
|
#define SDHCI_AMD_RESET_DLL_REGISTER 0x908
|
|
|
|
@@ -551,26 +556,66 @@ static void sdhci_acpi_amd_hs400_dll(struct sdhci_host *host)
|
|
}
|
|
|
|
/*
|
|
- * For AMD Platform it is required to disable the tuning
|
|
- * bit first controller to bring to HS Mode from HS200
|
|
- * mode, later enable to tune to HS400 mode.
|
|
+ * The initialization sequence for HS400 is:
|
|
+ * HS->HS200->Perform Tuning->HS->HS400
|
|
+ *
|
|
+ * The re-tuning sequence is:
|
|
+ * HS400->DDR52->HS->HS200->Perform Tuning->HS->HS400
|
|
+ *
|
|
+ * The AMD eMMC Controller can only use the tuned clock while in HS200 and HS400
|
|
+ * mode. If we switch to a different mode, we need to disable the tuned clock.
|
|
+ * If we have previously performed tuning and switch back to HS200 or
|
|
+ * HS400, we can re-enable the tuned clock.
|
|
+ *
|
|
*/
|
|
static void amd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
{
|
|
struct sdhci_host *host = mmc_priv(mmc);
|
|
+ struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
|
|
+ struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
|
|
unsigned int old_timing = host->timing;
|
|
+ u16 val;
|
|
|
|
sdhci_set_ios(mmc, ios);
|
|
- if (old_timing == MMC_TIMING_MMC_HS200 &&
|
|
- ios->timing == MMC_TIMING_MMC_HS)
|
|
- sdhci_writew(host, 0x9, SDHCI_HOST_CONTROL2);
|
|
- if (old_timing != MMC_TIMING_MMC_HS400 &&
|
|
- ios->timing == MMC_TIMING_MMC_HS400) {
|
|
- sdhci_writew(host, 0x80, SDHCI_HOST_CONTROL2);
|
|
- sdhci_acpi_amd_hs400_dll(host);
|
|
+
|
|
+ if (old_timing != host->timing && amd_host->tuned_clock) {
|
|
+ if (host->timing == MMC_TIMING_MMC_HS400 ||
|
|
+ host->timing == MMC_TIMING_MMC_HS200) {
|
|
+ val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
|
+ val |= SDHCI_CTRL_TUNED_CLK;
|
|
+ sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
|
|
+ } else {
|
|
+ val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
|
+ val &= ~SDHCI_CTRL_TUNED_CLK;
|
|
+ sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
|
|
+ }
|
|
+
|
|
+ /* DLL is only required for HS400 */
|
|
+ if (host->timing == MMC_TIMING_MMC_HS400 &&
|
|
+ !amd_host->dll_enabled) {
|
|
+ sdhci_acpi_amd_hs400_dll(host);
|
|
+ amd_host->dll_enabled = true;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+static int amd_sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
|
+{
|
|
+ int err;
|
|
+ struct sdhci_host *host = mmc_priv(mmc);
|
|
+ struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
|
|
+ struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
|
|
+
|
|
+ amd_host->tuned_clock = false;
|
|
+
|
|
+ err = sdhci_execute_tuning(mmc, opcode);
|
|
+
|
|
+ if (!err && !host->tuning_err)
|
|
+ amd_host->tuned_clock = true;
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
static const struct sdhci_ops sdhci_acpi_ops_amd = {
|
|
.set_clock = sdhci_set_clock,
|
|
.set_bus_width = sdhci_set_bus_width,
|
|
@@ -598,6 +643,7 @@ static int sdhci_acpi_emmc_amd_probe_slot(struct platform_device *pdev,
|
|
|
|
host->mmc_host_ops.select_drive_strength = amd_select_drive_strength;
|
|
host->mmc_host_ops.set_ios = amd_set_ios;
|
|
+ host->mmc_host_ops.execute_tuning = amd_sdhci_execute_tuning;
|
|
return 0;
|
|
}
|
|
|
|
@@ -609,6 +655,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_amd_emmc = {
|
|
SDHCI_QUIRK_32BIT_ADMA_SIZE,
|
|
.quirks2 = SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
|
|
.probe_slot = sdhci_acpi_emmc_amd_probe_slot,
|
|
+ .priv_size = sizeof(struct amd_sdhci_host),
|
|
};
|
|
|
|
struct sdhci_acpi_uid_slot {
|
|
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
|
|
index 9b66e8b374ed7..425aa898e797a 100644
|
|
--- a/drivers/mmc/host/sdhci-pci-core.c
|
|
+++ b/drivers/mmc/host/sdhci-pci-core.c
|
|
@@ -232,6 +232,14 @@ static void sdhci_pci_dumpregs(struct mmc_host *mmc)
|
|
sdhci_dumpregs(mmc_priv(mmc));
|
|
}
|
|
|
|
+static void sdhci_cqhci_reset(struct sdhci_host *host, u8 mask)
|
|
+{
|
|
+ if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) &&
|
|
+ host->mmc->cqe_private)
|
|
+ cqhci_deactivate(host->mmc);
|
|
+ sdhci_reset(host, mask);
|
|
+}
|
|
+
|
|
/*****************************************************************************\
|
|
* *
|
|
* Hardware specific quirk handling *
|
|
@@ -722,7 +730,7 @@ static const struct sdhci_ops sdhci_intel_glk_ops = {
|
|
.set_power = sdhci_intel_set_power,
|
|
.enable_dma = sdhci_pci_enable_dma,
|
|
.set_bus_width = sdhci_set_bus_width,
|
|
- .reset = sdhci_reset,
|
|
+ .reset = sdhci_cqhci_reset,
|
|
.set_uhs_signaling = sdhci_set_uhs_signaling,
|
|
.hw_reset = sdhci_pci_hw_reset,
|
|
.irq = sdhci_cqhci_irq,
|
|
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
|
|
index e37d271ca9636..c105356ad4cb7 100644
|
|
--- a/drivers/mmc/host/sdhci-tegra.c
|
|
+++ b/drivers/mmc/host/sdhci-tegra.c
|
|
@@ -100,6 +100,12 @@
|
|
#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)
|
|
#define NVQUIRK_CQHCI_DCMD_R1B_CMD_TIMING BIT(9)
|
|
|
|
+/*
|
|
+ * NVQUIRK_HAS_TMCLK is for SoC's having separate timeout clock for Tegra
|
|
+ * SDMMC hardware data timeout.
|
|
+ */
|
|
+#define NVQUIRK_HAS_TMCLK BIT(10)
|
|
+
|
|
/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
|
|
#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000
|
|
|
|
@@ -130,6 +136,7 @@ struct sdhci_tegra_autocal_offsets {
|
|
struct sdhci_tegra {
|
|
const struct sdhci_tegra_soc_data *soc_data;
|
|
struct gpio_desc *power_gpio;
|
|
+ struct clk *tmclk;
|
|
bool ddr_signaling;
|
|
bool pad_calib_required;
|
|
bool pad_control_available;
|
|
@@ -1385,7 +1392,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
|
|
NVQUIRK_HAS_PADCALIB |
|
|
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
|
|
NVQUIRK_ENABLE_SDR50 |
|
|
- NVQUIRK_ENABLE_SDR104,
|
|
+ NVQUIRK_ENABLE_SDR104 |
|
|
+ NVQUIRK_HAS_TMCLK,
|
|
.min_tap_delay = 106,
|
|
.max_tap_delay = 185,
|
|
};
|
|
@@ -1422,6 +1430,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
|
|
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
|
|
NVQUIRK_ENABLE_SDR50 |
|
|
NVQUIRK_ENABLE_SDR104 |
|
|
+ NVQUIRK_HAS_TMCLK |
|
|
NVQUIRK_CQHCI_DCMD_R1B_CMD_TIMING,
|
|
.min_tap_delay = 84,
|
|
.max_tap_delay = 136,
|
|
@@ -1434,7 +1443,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra194 = {
|
|
NVQUIRK_HAS_PADCALIB |
|
|
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
|
|
NVQUIRK_ENABLE_SDR50 |
|
|
- NVQUIRK_ENABLE_SDR104,
|
|
+ NVQUIRK_ENABLE_SDR104 |
|
|
+ NVQUIRK_HAS_TMCLK,
|
|
.min_tap_delay = 96,
|
|
.max_tap_delay = 139,
|
|
};
|
|
@@ -1562,6 +1572,43 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
|
|
goto err_power_req;
|
|
}
|
|
|
|
+ /*
|
|
+ * Tegra210 has a separate SDMMC_LEGACY_TM clock used for host
|
|
+ * timeout clock and SW can choose TMCLK or SDCLK for hardware
|
|
+ * data timeout through the bit USE_TMCLK_FOR_DATA_TIMEOUT of
|
|
+ * the register SDHCI_TEGRA_VENDOR_SYS_SW_CTRL.
|
|
+ *
|
|
+ * USE_TMCLK_FOR_DATA_TIMEOUT bit default is set to 1 and SDMMC uses
|
|
+ * 12Mhz TMCLK which is advertised in host capability register.
|
|
+ * With TMCLK of 12Mhz provides maximum data timeout period that can
|
|
+ * be achieved is 11s better than using SDCLK for data timeout.
|
|
+ *
|
|
+ * So, TMCLK is set to 12Mhz and kept enabled all the time on SoC's
|
|
+ * supporting separate TMCLK.
|
|
+ */
|
|
+
|
|
+ if (soc_data->nvquirks & NVQUIRK_HAS_TMCLK) {
|
|
+ clk = devm_clk_get(&pdev->dev, "tmclk");
|
|
+ if (IS_ERR(clk)) {
|
|
+ rc = PTR_ERR(clk);
|
|
+ if (rc == -EPROBE_DEFER)
|
|
+ goto err_power_req;
|
|
+
|
|
+ dev_warn(&pdev->dev, "failed to get tmclk: %d\n", rc);
|
|
+ clk = NULL;
|
|
+ }
|
|
+
|
|
+ clk_set_rate(clk, 12000000);
|
|
+ rc = clk_prepare_enable(clk);
|
|
+ if (rc) {
|
|
+ dev_err(&pdev->dev,
|
|
+ "failed to enable tmclk: %d\n", rc);
|
|
+ goto err_power_req;
|
|
+ }
|
|
+
|
|
+ tegra_host->tmclk = clk;
|
|
+ }
|
|
+
|
|
clk = devm_clk_get(mmc_dev(host->mmc), NULL);
|
|
if (IS_ERR(clk)) {
|
|
rc = PTR_ERR(clk);
|
|
@@ -1605,6 +1652,7 @@ err_add_host:
|
|
err_rst_get:
|
|
clk_disable_unprepare(pltfm_host->clk);
|
|
err_clk_get:
|
|
+ clk_disable_unprepare(tegra_host->tmclk);
|
|
err_power_req:
|
|
err_parse_dt:
|
|
sdhci_pltfm_free(pdev);
|
|
@@ -1622,6 +1670,7 @@ static int sdhci_tegra_remove(struct platform_device *pdev)
|
|
reset_control_assert(tegra_host->rst);
|
|
usleep_range(2000, 4000);
|
|
clk_disable_unprepare(pltfm_host->clk);
|
|
+ clk_disable_unprepare(tegra_host->tmclk);
|
|
|
|
sdhci_pltfm_free(pdev);
|
|
|
|
diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
|
|
index 8d50aacd19e51..84c4319e3b31f 100644
|
|
--- a/drivers/net/dsa/microchip/ksz8795.c
|
|
+++ b/drivers/net/dsa/microchip/ksz8795.c
|
|
@@ -1270,9 +1270,6 @@ static int ksz8795_switch_init(struct ksz_device *dev)
|
|
/* set the real number of ports */
|
|
dev->ds->num_ports = dev->port_cnt;
|
|
|
|
- /* set the real number of ports */
|
|
- dev->ds->num_ports = dev->port_cnt;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
|
|
index b15da9a8e3bb9..49ab1346dc3f7 100644
|
|
--- a/drivers/net/dsa/microchip/ksz9477.c
|
|
+++ b/drivers/net/dsa/microchip/ksz9477.c
|
|
@@ -515,9 +515,6 @@ static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
|
|
PORT_VLAN_LOOKUP_VID_0, false);
|
|
}
|
|
|
|
- /* set the real number of ports */
|
|
- dev->ds->num_ports = dev->port_cnt;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
|
|
index dc9a3bb241149..00d680cb44418 100644
|
|
--- a/drivers/net/dsa/mt7530.c
|
|
+++ b/drivers/net/dsa/mt7530.c
|
|
@@ -1456,7 +1456,7 @@ unsupported:
|
|
phylink_set(mask, 100baseT_Full);
|
|
|
|
if (state->interface != PHY_INTERFACE_MODE_MII) {
|
|
- phylink_set(mask, 1000baseT_Half);
|
|
+ /* This switch only supports 1G full-duplex. */
|
|
phylink_set(mask, 1000baseT_Full);
|
|
if (port == 5)
|
|
phylink_set(mask, 1000baseX_Full);
|
|
diff --git a/drivers/net/ethernet/arc/emac_mdio.c b/drivers/net/ethernet/arc/emac_mdio.c
|
|
index 0187dbf3b87df..54cdafdd067db 100644
|
|
--- a/drivers/net/ethernet/arc/emac_mdio.c
|
|
+++ b/drivers/net/ethernet/arc/emac_mdio.c
|
|
@@ -153,6 +153,7 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
|
|
if (IS_ERR(data->reset_gpio)) {
|
|
error = PTR_ERR(data->reset_gpio);
|
|
dev_err(priv->dev, "Failed to request gpio: %d\n", error);
|
|
+ mdiobus_free(bus);
|
|
return error;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
|
|
index 4dfdb5a58025b..71eb8914e620b 100644
|
|
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
|
|
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
|
|
@@ -2453,8 +2453,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|
priv->tx_rings = devm_kcalloc(&pdev->dev, txq,
|
|
sizeof(struct bcm_sysport_tx_ring),
|
|
GFP_KERNEL);
|
|
- if (!priv->tx_rings)
|
|
- return -ENOMEM;
|
|
+ if (!priv->tx_rings) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_free_netdev;
|
|
+ }
|
|
|
|
priv->is_lite = params->is_lite;
|
|
priv->num_rx_desc_words = params->num_rx_desc_words;
|
|
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
index 2cbfe0cd7eefa..4030020f92be5 100644
|
|
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
@@ -1143,6 +1143,9 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
|
|
|
|
static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay)
|
|
{
|
|
+ if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)))
|
|
+ return;
|
|
+
|
|
if (BNXT_PF(bp))
|
|
queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay);
|
|
else
|
|
@@ -1159,10 +1162,12 @@ static void bnxt_queue_sp_work(struct bnxt *bp)
|
|
|
|
static void bnxt_cancel_sp_work(struct bnxt *bp)
|
|
{
|
|
- if (BNXT_PF(bp))
|
|
+ if (BNXT_PF(bp)) {
|
|
flush_workqueue(bnxt_pf_wq);
|
|
- else
|
|
+ } else {
|
|
cancel_work_sync(&bp->sp_task);
|
|
+ cancel_delayed_work_sync(&bp->fw_reset_task);
|
|
+ }
|
|
}
|
|
|
|
static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
|
|
@@ -8933,16 +8938,19 @@ static ssize_t bnxt_show_temp(struct device *dev,
|
|
struct hwrm_temp_monitor_query_input req = {0};
|
|
struct hwrm_temp_monitor_query_output *resp;
|
|
struct bnxt *bp = dev_get_drvdata(dev);
|
|
- u32 temp = 0;
|
|
+ u32 len = 0;
|
|
|
|
resp = bp->hwrm_cmd_resp_addr;
|
|
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TEMP_MONITOR_QUERY, -1, -1);
|
|
mutex_lock(&bp->hwrm_cmd_lock);
|
|
- if (!_hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT))
|
|
- temp = resp->temp * 1000; /* display millidegree */
|
|
+ if (!_hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT))
|
|
+ len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
|
|
mutex_unlock(&bp->hwrm_cmd_lock);
|
|
|
|
- return sprintf(buf, "%u\n", temp);
|
|
+ if (len)
|
|
+ return len;
|
|
+
|
|
+ return sprintf(buf, "unknown\n");
|
|
}
|
|
static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
|
|
|
|
@@ -9124,15 +9132,15 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
|
|
}
|
|
}
|
|
|
|
- bnxt_enable_napi(bp);
|
|
- bnxt_debug_dev_init(bp);
|
|
-
|
|
rc = bnxt_init_nic(bp, irq_re_init);
|
|
if (rc) {
|
|
netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
|
|
- goto open_err;
|
|
+ goto open_err_irq;
|
|
}
|
|
|
|
+ bnxt_enable_napi(bp);
|
|
+ bnxt_debug_dev_init(bp);
|
|
+
|
|
if (link_re_init) {
|
|
mutex_lock(&bp->link_lock);
|
|
rc = bnxt_update_phy_setting(bp);
|
|
@@ -9163,10 +9171,6 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
|
|
bnxt_vf_reps_open(bp);
|
|
return 0;
|
|
|
|
-open_err:
|
|
- bnxt_debug_dev_exit(bp);
|
|
- bnxt_disable_napi(bp);
|
|
-
|
|
open_err_irq:
|
|
bnxt_del_napi(bp);
|
|
|
|
@@ -11386,6 +11390,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
|
|
unregister_netdev(dev);
|
|
bnxt_dl_unregister(bp);
|
|
bnxt_shutdown_tc(bp);
|
|
+ clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
|
|
bnxt_cancel_sp_work(bp);
|
|
bp->sp_event = 0;
|
|
|
|
@@ -11900,6 +11905,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
(long)pci_resource_start(pdev, 0), dev->dev_addr);
|
|
pcie_print_link_status(pdev);
|
|
|
|
+ pci_save_state(pdev);
|
|
return 0;
|
|
|
|
init_err_cleanup:
|
|
@@ -12066,6 +12072,8 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
|
|
"Cannot re-enable PCI device after reset.\n");
|
|
} else {
|
|
pci_set_master(pdev);
|
|
+ pci_restore_state(pdev);
|
|
+ pci_save_state(pdev);
|
|
|
|
err = bnxt_hwrm_func_reset(bp);
|
|
if (!err && netif_running(netdev))
|
|
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
|
|
index 1f512e7c3d434..fd01bcc8e28d4 100644
|
|
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
|
|
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
|
|
@@ -769,7 +769,7 @@ static void bnxt_get_channels(struct net_device *dev,
|
|
int max_tx_sch_inputs;
|
|
|
|
/* Get the most up-to-date max_tx_sch_inputs. */
|
|
- if (BNXT_NEW_RM(bp))
|
|
+ if (netif_running(dev) && BNXT_NEW_RM(bp))
|
|
bnxt_hwrm_func_resc_qcaps(bp, false);
|
|
max_tx_sch_inputs = hw_resc->max_tx_sch_inputs;
|
|
|
|
@@ -2161,6 +2161,9 @@ static int bnxt_get_nvram_directory(struct net_device *dev, u32 len, u8 *data)
|
|
if (rc != 0)
|
|
return rc;
|
|
|
|
+ if (!dir_entries || !entry_length)
|
|
+ return -EIO;
|
|
+
|
|
/* Insert 2 bytes of directory info (count and size of entries) */
|
|
if (len < 2)
|
|
return -EINVAL;
|
|
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
|
|
index e12ba81288e64..70bd79dc43f2e 100644
|
|
--- a/drivers/net/ethernet/broadcom/tg3.c
|
|
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
|
@@ -7227,8 +7227,8 @@ static inline void tg3_reset_task_schedule(struct tg3 *tp)
|
|
|
|
static inline void tg3_reset_task_cancel(struct tg3 *tp)
|
|
{
|
|
- cancel_work_sync(&tp->reset_task);
|
|
- tg3_flag_clear(tp, RESET_TASK_PENDING);
|
|
+ if (test_and_clear_bit(TG3_FLAG_RESET_TASK_PENDING, tp->tg3_flags))
|
|
+ cancel_work_sync(&tp->reset_task);
|
|
tg3_flag_clear(tp, TX_RECOVERY_PENDING);
|
|
}
|
|
|
|
@@ -11219,18 +11219,27 @@ static void tg3_reset_task(struct work_struct *work)
|
|
|
|
tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
|
|
err = tg3_init_hw(tp, true);
|
|
- if (err)
|
|
+ if (err) {
|
|
+ tg3_full_unlock(tp);
|
|
+ tp->irq_sync = 0;
|
|
+ tg3_napi_enable(tp);
|
|
+ /* Clear this flag so that tg3_reset_task_cancel() will not
|
|
+ * call cancel_work_sync() and wait forever.
|
|
+ */
|
|
+ tg3_flag_clear(tp, RESET_TASK_PENDING);
|
|
+ dev_close(tp->dev);
|
|
goto out;
|
|
+ }
|
|
|
|
tg3_netif_start(tp);
|
|
|
|
-out:
|
|
tg3_full_unlock(tp);
|
|
|
|
if (!err)
|
|
tg3_phy_start(tp);
|
|
|
|
tg3_flag_clear(tp, RESET_TASK_PENDING);
|
|
+out:
|
|
rtnl_unlock();
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
|
|
index 3de8a5e83b6c7..d7fefdbf3e575 100644
|
|
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
|
|
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
|
|
@@ -62,6 +62,7 @@ static struct thermal_zone_device_ops cxgb4_thermal_ops = {
|
|
int cxgb4_thermal_init(struct adapter *adap)
|
|
{
|
|
struct ch_thermal *ch_thermal = &adap->ch_thermal;
|
|
+ char ch_tz_name[THERMAL_NAME_LENGTH];
|
|
int num_trip = CXGB4_NUM_TRIPS;
|
|
u32 param, val;
|
|
int ret;
|
|
@@ -82,7 +83,8 @@ int cxgb4_thermal_init(struct adapter *adap)
|
|
ch_thermal->trip_type = THERMAL_TRIP_CRITICAL;
|
|
}
|
|
|
|
- ch_thermal->tzdev = thermal_zone_device_register("cxgb4", num_trip,
|
|
+ snprintf(ch_tz_name, sizeof(ch_tz_name), "cxgb4_%s", adap->name);
|
|
+ ch_thermal->tzdev = thermal_zone_device_register(ch_tz_name, num_trip,
|
|
0, adap,
|
|
&cxgb4_thermal_ops,
|
|
NULL, 0, 0);
|
|
@@ -97,7 +99,9 @@ int cxgb4_thermal_init(struct adapter *adap)
|
|
|
|
int cxgb4_thermal_remove(struct adapter *adap)
|
|
{
|
|
- if (adap->ch_thermal.tzdev)
|
|
+ if (adap->ch_thermal.tzdev) {
|
|
thermal_zone_device_unregister(adap->ch_thermal.tzdev);
|
|
+ adap->ch_thermal.tzdev = NULL;
|
|
+ }
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
|
|
index 28d4c54505f9a..c9fb1ec625d8b 100644
|
|
--- a/drivers/net/ethernet/cortina/gemini.c
|
|
+++ b/drivers/net/ethernet/cortina/gemini.c
|
|
@@ -2445,8 +2445,8 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
|
|
port->reset = devm_reset_control_get_exclusive(dev, NULL);
|
|
if (IS_ERR(port->reset)) {
|
|
dev_err(dev, "no reset\n");
|
|
- clk_disable_unprepare(port->pclk);
|
|
- return PTR_ERR(port->reset);
|
|
+ ret = PTR_ERR(port->reset);
|
|
+ goto unprepare;
|
|
}
|
|
reset_control_reset(port->reset);
|
|
usleep_range(100, 500);
|
|
@@ -2501,25 +2501,25 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
|
|
IRQF_SHARED,
|
|
port_names[port->id],
|
|
port);
|
|
- if (ret) {
|
|
- clk_disable_unprepare(port->pclk);
|
|
- return ret;
|
|
- }
|
|
+ if (ret)
|
|
+ goto unprepare;
|
|
|
|
ret = register_netdev(netdev);
|
|
- if (!ret) {
|
|
+ if (ret)
|
|
+ goto unprepare;
|
|
+
|
|
+ netdev_info(netdev,
|
|
+ "irq %d, DMA @ 0x%pap, GMAC @ 0x%pap\n",
|
|
+ port->irq, &dmares->start,
|
|
+ &gmacres->start);
|
|
+ ret = gmac_setup_phy(netdev);
|
|
+ if (ret)
|
|
netdev_info(netdev,
|
|
- "irq %d, DMA @ 0x%pap, GMAC @ 0x%pap\n",
|
|
- port->irq, &dmares->start,
|
|
- &gmacres->start);
|
|
- ret = gmac_setup_phy(netdev);
|
|
- if (ret)
|
|
- netdev_info(netdev,
|
|
- "PHY init failed, deferring to ifup time\n");
|
|
- return 0;
|
|
- }
|
|
+ "PHY init failed, deferring to ifup time\n");
|
|
+ return 0;
|
|
|
|
- port->netdev = NULL;
|
|
+unprepare:
|
|
+ clk_disable_unprepare(port->pclk);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
|
|
index eb69e5c81a4d0..6d5d53cfc7ab4 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
|
|
@@ -2296,8 +2296,10 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
|
|
priv->enet_ver = AE_VERSION_1;
|
|
else if (acpi_dev_found(hns_enet_acpi_match[1].id))
|
|
priv->enet_ver = AE_VERSION_2;
|
|
- else
|
|
- return -ENXIO;
|
|
+ else {
|
|
+ ret = -ENXIO;
|
|
+ goto out_read_prop_fail;
|
|
+ }
|
|
|
|
/* try to find port-idx-in-ae first */
|
|
ret = acpi_node_get_property_reference(dev->fwnode,
|
|
@@ -2313,7 +2315,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
|
|
priv->fwnode = args.fwnode;
|
|
} else {
|
|
dev_err(dev, "cannot read cfg data from OF or acpi\n");
|
|
- return -ENXIO;
|
|
+ ret = -ENXIO;
|
|
+ goto out_read_prop_fail;
|
|
}
|
|
|
|
ret = device_property_read_u32(dev, "port-idx-in-ae", &port_id);
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
|
|
index 1a11bc0e16123..cfa0bba3940fb 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
|
|
@@ -114,7 +114,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
|
|
goto err_out;
|
|
|
|
for (i = 0; i <= buddy->max_order; ++i) {
|
|
- s = BITS_TO_LONGS(1 << (buddy->max_order - i));
|
|
+ s = BITS_TO_LONGS(1UL << (buddy->max_order - i));
|
|
buddy->bits[i] = kvmalloc_array(s, sizeof(long), GFP_KERNEL | __GFP_ZERO);
|
|
if (!buddy->bits[i])
|
|
goto err_out_free;
|
|
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
|
|
index 30cdabf64ccc1..907ae1359a7c1 100644
|
|
--- a/drivers/net/ethernet/renesas/ravb_main.c
|
|
+++ b/drivers/net/ethernet/renesas/ravb_main.c
|
|
@@ -1336,6 +1336,51 @@ static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
|
|
return error;
|
|
}
|
|
|
|
+/* MDIO bus init function */
|
|
+static int ravb_mdio_init(struct ravb_private *priv)
|
|
+{
|
|
+ struct platform_device *pdev = priv->pdev;
|
|
+ struct device *dev = &pdev->dev;
|
|
+ int error;
|
|
+
|
|
+ /* Bitbang init */
|
|
+ priv->mdiobb.ops = &bb_ops;
|
|
+
|
|
+ /* MII controller setting */
|
|
+ priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
|
|
+ if (!priv->mii_bus)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ /* Hook up MII support for ethtool */
|
|
+ priv->mii_bus->name = "ravb_mii";
|
|
+ priv->mii_bus->parent = dev;
|
|
+ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
|
|
+ pdev->name, pdev->id);
|
|
+
|
|
+ /* Register MDIO bus */
|
|
+ error = of_mdiobus_register(priv->mii_bus, dev->of_node);
|
|
+ if (error)
|
|
+ goto out_free_bus;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+out_free_bus:
|
|
+ free_mdio_bitbang(priv->mii_bus);
|
|
+ return error;
|
|
+}
|
|
+
|
|
+/* MDIO bus release function */
|
|
+static int ravb_mdio_release(struct ravb_private *priv)
|
|
+{
|
|
+ /* Unregister mdio bus */
|
|
+ mdiobus_unregister(priv->mii_bus);
|
|
+
|
|
+ /* Free bitbang info */
|
|
+ free_mdio_bitbang(priv->mii_bus);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* Network device open function for Ethernet AVB */
|
|
static int ravb_open(struct net_device *ndev)
|
|
{
|
|
@@ -1344,6 +1389,13 @@ static int ravb_open(struct net_device *ndev)
|
|
struct device *dev = &pdev->dev;
|
|
int error;
|
|
|
|
+ /* MDIO bus init */
|
|
+ error = ravb_mdio_init(priv);
|
|
+ if (error) {
|
|
+ netdev_err(ndev, "failed to initialize MDIO\n");
|
|
+ return error;
|
|
+ }
|
|
+
|
|
napi_enable(&priv->napi[RAVB_BE]);
|
|
napi_enable(&priv->napi[RAVB_NC]);
|
|
|
|
@@ -1421,6 +1473,7 @@ out_free_irq:
|
|
out_napi_off:
|
|
napi_disable(&priv->napi[RAVB_NC]);
|
|
napi_disable(&priv->napi[RAVB_BE]);
|
|
+ ravb_mdio_release(priv);
|
|
return error;
|
|
}
|
|
|
|
@@ -1730,6 +1783,8 @@ static int ravb_close(struct net_device *ndev)
|
|
ravb_ring_free(ndev, RAVB_BE);
|
|
ravb_ring_free(ndev, RAVB_NC);
|
|
|
|
+ ravb_mdio_release(priv);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1881,51 +1936,6 @@ static const struct net_device_ops ravb_netdev_ops = {
|
|
.ndo_set_features = ravb_set_features,
|
|
};
|
|
|
|
-/* MDIO bus init function */
|
|
-static int ravb_mdio_init(struct ravb_private *priv)
|
|
-{
|
|
- struct platform_device *pdev = priv->pdev;
|
|
- struct device *dev = &pdev->dev;
|
|
- int error;
|
|
-
|
|
- /* Bitbang init */
|
|
- priv->mdiobb.ops = &bb_ops;
|
|
-
|
|
- /* MII controller setting */
|
|
- priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
|
|
- if (!priv->mii_bus)
|
|
- return -ENOMEM;
|
|
-
|
|
- /* Hook up MII support for ethtool */
|
|
- priv->mii_bus->name = "ravb_mii";
|
|
- priv->mii_bus->parent = dev;
|
|
- snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
|
|
- pdev->name, pdev->id);
|
|
-
|
|
- /* Register MDIO bus */
|
|
- error = of_mdiobus_register(priv->mii_bus, dev->of_node);
|
|
- if (error)
|
|
- goto out_free_bus;
|
|
-
|
|
- return 0;
|
|
-
|
|
-out_free_bus:
|
|
- free_mdio_bitbang(priv->mii_bus);
|
|
- return error;
|
|
-}
|
|
-
|
|
-/* MDIO bus release function */
|
|
-static int ravb_mdio_release(struct ravb_private *priv)
|
|
-{
|
|
- /* Unregister mdio bus */
|
|
- mdiobus_unregister(priv->mii_bus);
|
|
-
|
|
- /* Free bitbang info */
|
|
- free_mdio_bitbang(priv->mii_bus);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
static const struct of_device_id ravb_match_table[] = {
|
|
{ .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 },
|
|
{ .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 },
|
|
@@ -2166,13 +2176,6 @@ static int ravb_probe(struct platform_device *pdev)
|
|
eth_hw_addr_random(ndev);
|
|
}
|
|
|
|
- /* MDIO bus init */
|
|
- error = ravb_mdio_init(priv);
|
|
- if (error) {
|
|
- dev_err(&pdev->dev, "failed to initialize MDIO\n");
|
|
- goto out_dma_free;
|
|
- }
|
|
-
|
|
netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll, 64);
|
|
netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll, 64);
|
|
|
|
@@ -2194,8 +2197,6 @@ static int ravb_probe(struct platform_device *pdev)
|
|
out_napi_del:
|
|
netif_napi_del(&priv->napi[RAVB_NC]);
|
|
netif_napi_del(&priv->napi[RAVB_BE]);
|
|
- ravb_mdio_release(priv);
|
|
-out_dma_free:
|
|
dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
|
|
priv->desc_bat_dma);
|
|
|
|
@@ -2227,7 +2228,6 @@ static int ravb_remove(struct platform_device *pdev)
|
|
unregister_netdev(ndev);
|
|
netif_napi_del(&priv->napi[RAVB_NC]);
|
|
netif_napi_del(&priv->napi[RAVB_BE]);
|
|
- ravb_mdio_release(priv);
|
|
pm_runtime_disable(&pdev->dev);
|
|
free_netdev(ndev);
|
|
platform_set_drvdata(pdev, NULL);
|
|
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
|
|
index 39df8c8feb6ce..e7b4d93e3f288 100644
|
|
--- a/drivers/net/ethernet/ti/cpsw.c
|
|
+++ b/drivers/net/ethernet/ti/cpsw.c
|
|
@@ -2209,7 +2209,7 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
|
|
HOST_PORT_NUM, ALE_VLAN, vid);
|
|
ret |= cpsw_ale_del_mcast(cpsw->ale, priv->ndev->broadcast,
|
|
0, ALE_VLAN, vid);
|
|
- ret |= cpsw_ale_flush_multicast(cpsw->ale, 0, vid);
|
|
+ ret |= cpsw_ale_flush_multicast(cpsw->ale, ALE_PORT_HOST, vid);
|
|
err:
|
|
pm_runtime_put(cpsw->dev);
|
|
return ret;
|
|
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
|
|
index d89ec99abcd63..634bdea38ecb3 100644
|
|
--- a/drivers/net/gtp.c
|
|
+++ b/drivers/net/gtp.c
|
|
@@ -1182,6 +1182,7 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
|
|
goto nlmsg_failure;
|
|
|
|
if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||
|
|
+ nla_put_u32(skb, GTPA_LINK, pctx->dev->ifindex) ||
|
|
nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) ||
|
|
nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr))
|
|
goto nla_put_failure;
|
|
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
|
|
index e39f41efda3ec..7bc6e8f856fe0 100644
|
|
--- a/drivers/net/usb/asix_common.c
|
|
+++ b/drivers/net/usb/asix_common.c
|
|
@@ -296,7 +296,7 @@ int asix_read_phy_addr(struct usbnet *dev, int internal)
|
|
|
|
netdev_dbg(dev->net, "asix_get_phy_addr()\n");
|
|
|
|
- if (ret < 0) {
|
|
+ if (ret < 2) {
|
|
netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret);
|
|
goto out;
|
|
}
|
|
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
|
|
index ff5681da8780d..3cb017fa3a790 100644
|
|
--- a/drivers/nvme/host/core.c
|
|
+++ b/drivers/nvme/host/core.c
|
|
@@ -4012,7 +4012,7 @@ static void nvme_free_ctrl(struct device *dev)
|
|
container_of(dev, struct nvme_ctrl, ctrl_device);
|
|
struct nvme_subsystem *subsys = ctrl->subsys;
|
|
|
|
- if (subsys && ctrl->instance != subsys->instance)
|
|
+ if (!subsys || ctrl->instance != subsys->instance)
|
|
ida_simple_remove(&nvme_instance_ida, ctrl->instance);
|
|
|
|
kfree(ctrl->effects);
|
|
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
|
|
index 57a4062cbb59e..7d7176369edf7 100644
|
|
--- a/drivers/nvme/target/core.c
|
|
+++ b/drivers/nvme/target/core.c
|
|
@@ -369,6 +369,9 @@ static void nvmet_keep_alive_timer(struct work_struct *work)
|
|
|
|
static void nvmet_start_keep_alive_timer(struct nvmet_ctrl *ctrl)
|
|
{
|
|
+ if (unlikely(ctrl->kato == 0))
|
|
+ return;
|
|
+
|
|
pr_debug("ctrl %d start keep-alive timer for %d secs\n",
|
|
ctrl->cntlid, ctrl->kato);
|
|
|
|
@@ -378,6 +381,9 @@ static void nvmet_start_keep_alive_timer(struct nvmet_ctrl *ctrl)
|
|
|
|
static void nvmet_stop_keep_alive_timer(struct nvmet_ctrl *ctrl)
|
|
{
|
|
+ if (unlikely(ctrl->kato == 0))
|
|
+ return;
|
|
+
|
|
pr_debug("ctrl %d stop keep-alive\n", ctrl->cntlid);
|
|
|
|
cancel_delayed_work_sync(&ctrl->ka_work);
|
|
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
|
|
index ce8d819f86ccc..fc35f7ae67b0a 100644
|
|
--- a/drivers/nvme/target/fc.c
|
|
+++ b/drivers/nvme/target/fc.c
|
|
@@ -1994,9 +1994,9 @@ nvmet_fc_fod_op_done(struct nvmet_fc_fcp_iod *fod)
|
|
return;
|
|
if (fcpreq->fcp_error ||
|
|
fcpreq->transferred_length != fcpreq->transfer_length) {
|
|
- spin_lock(&fod->flock);
|
|
+ spin_lock_irqsave(&fod->flock, flags);
|
|
fod->abort = true;
|
|
- spin_unlock(&fod->flock);
|
|
+ spin_unlock_irqrestore(&fod->flock, flags);
|
|
|
|
nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
|
|
return;
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
index 3439f6ad63380..e80e82a276e93 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
|
@@ -159,6 +159,7 @@ static int cedrus_request_validate(struct media_request *req)
|
|
struct v4l2_ctrl *ctrl_test;
|
|
unsigned int count;
|
|
unsigned int i;
|
|
+ int ret = 0;
|
|
|
|
list_for_each_entry(obj, &req->objects, list) {
|
|
struct vb2_buffer *vb;
|
|
@@ -203,12 +204,16 @@ static int cedrus_request_validate(struct media_request *req)
|
|
if (!ctrl_test) {
|
|
v4l2_info(&ctx->dev->v4l2_dev,
|
|
"Missing required codec control\n");
|
|
- return -ENOENT;
|
|
+ ret = -ENOENT;
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
v4l2_ctrl_request_hdl_put(hdl);
|
|
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
return vb2_request_validate(req);
|
|
}
|
|
|
|
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
|
|
index bf7bae42c141c..6dc879fea9c8a 100644
|
|
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
|
|
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
|
|
@@ -1,6 +1,6 @@
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
- * Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/bitops.h>
|
|
@@ -191,7 +191,7 @@ static int qpnp_tm_get_temp(void *data, int *temp)
|
|
chip->temp = mili_celsius;
|
|
}
|
|
|
|
- *temp = chip->temp < 0 ? 0 : chip->temp;
|
|
+ *temp = chip->temp;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
|
|
index 63b02bfb2adf6..fdb8a495ab69a 100644
|
|
--- a/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
|
|
+++ b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
|
|
@@ -37,20 +37,21 @@ static struct temp_sensor_data omap4430_mpu_temp_sensor_data = {
|
|
|
|
/*
|
|
* Temperature values in milli degree celsius
|
|
- * ADC code values from 530 to 923
|
|
+ * ADC code values from 13 to 107, see TRM
|
|
+ * "18.4.10.2.3 ADC Codes Versus Temperature".
|
|
*/
|
|
static const int
|
|
omap4430_adc_to_temp[OMAP4430_ADC_END_VALUE - OMAP4430_ADC_START_VALUE + 1] = {
|
|
- -38000, -35000, -34000, -32000, -30000, -28000, -26000, -24000, -22000,
|
|
- -20000, -18000, -17000, -15000, -13000, -12000, -10000, -8000, -6000,
|
|
- -5000, -3000, -1000, 0, 2000, 3000, 5000, 6000, 8000, 10000, 12000,
|
|
- 13000, 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28000, 30000,
|
|
- 32000, 33000, 35000, 37000, 38000, 40000, 42000, 43000, 45000, 47000,
|
|
- 48000, 50000, 52000, 53000, 55000, 57000, 58000, 60000, 62000, 64000,
|
|
- 66000, 68000, 70000, 71000, 73000, 75000, 77000, 78000, 80000, 82000,
|
|
- 83000, 85000, 87000, 88000, 90000, 92000, 93000, 95000, 97000, 98000,
|
|
- 100000, 102000, 103000, 105000, 107000, 109000, 111000, 113000, 115000,
|
|
- 117000, 118000, 120000, 122000, 123000,
|
|
+ -40000, -38000, -35000, -34000, -32000, -30000, -28000, -26000, -24000,
|
|
+ -22000, -20000, -18500, -17000, -15000, -13500, -12000, -10000, -8000,
|
|
+ -6500, -5000, -3500, -1500, 0, 2000, 3500, 5000, 6500, 8500, 10000,
|
|
+ 12000, 13500, 15000, 17000, 19000, 21000, 23000, 25000, 27000, 28500,
|
|
+ 30000, 32000, 33500, 35000, 37000, 38500, 40000, 42000, 43500, 45000,
|
|
+ 47000, 48500, 50000, 52000, 53500, 55000, 57000, 58500, 60000, 62000,
|
|
+ 64000, 66000, 68000, 70000, 71500, 73500, 75000, 77000, 78500, 80000,
|
|
+ 82000, 83500, 85000, 87000, 88500, 90000, 92000, 93500, 95000, 97000,
|
|
+ 98500, 100000, 102000, 103500, 105000, 107000, 109000, 111000, 113000,
|
|
+ 115000, 117000, 118500, 120000, 122000, 123500, 125000,
|
|
};
|
|
|
|
/* OMAP4430 data */
|
|
diff --git a/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
|
|
index a453ff8eb313e..9a3955c3853ba 100644
|
|
--- a/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
|
|
+++ b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
|
|
@@ -53,9 +53,13 @@
|
|
* and thresholds for OMAP4430.
|
|
*/
|
|
|
|
-/* ADC conversion table limits */
|
|
-#define OMAP4430_ADC_START_VALUE 0
|
|
-#define OMAP4430_ADC_END_VALUE 127
|
|
+/*
|
|
+ * ADC conversion table limits. Ignore values outside the TRM listed
|
|
+ * range to avoid bogus thermal shutdowns. See omap4430 TRM chapter
|
|
+ * "18.4.10.2.3 ADC Codes Versus Temperature".
|
|
+ */
|
|
+#define OMAP4430_ADC_START_VALUE 13
|
|
+#define OMAP4430_ADC_END_VALUE 107
|
|
/* bandgap clock limits (no control on 4430) */
|
|
#define OMAP4430_MAX_FREQ 32768
|
|
#define OMAP4430_MIN_FREQ 32768
|
|
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
|
|
index f98a79172ad23..0b184256034fb 100644
|
|
--- a/drivers/tty/serial/qcom_geni_serial.c
|
|
+++ b/drivers/tty/serial/qcom_geni_serial.c
|
|
@@ -1063,7 +1063,7 @@ static unsigned int qcom_geni_serial_tx_empty(struct uart_port *uport)
|
|
}
|
|
|
|
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
|
|
-static int __init qcom_geni_console_setup(struct console *co, char *options)
|
|
+static int qcom_geni_console_setup(struct console *co, char *options)
|
|
{
|
|
struct uart_port *uport;
|
|
struct qcom_geni_serial_port *port;
|
|
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
|
|
index 02206162eaa9e..0d16f9806655f 100644
|
|
--- a/drivers/vfio/pci/vfio_pci.c
|
|
+++ b/drivers/vfio/pci/vfio_pci.c
|
|
@@ -27,6 +27,7 @@
|
|
#include <linux/vfio.h>
|
|
#include <linux/vgaarb.h>
|
|
#include <linux/nospec.h>
|
|
+#include <linux/sched/mm.h>
|
|
|
|
#include "vfio_pci_private.h"
|
|
|
|
@@ -177,6 +178,7 @@ no_mmap:
|
|
|
|
static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev);
|
|
static void vfio_pci_disable(struct vfio_pci_device *vdev);
|
|
+static int vfio_pci_try_zap_and_vma_lock_cb(struct pci_dev *pdev, void *data);
|
|
|
|
/*
|
|
* INTx masking requires the ability to disable INTx signaling via PCI_COMMAND
|
|
@@ -688,6 +690,12 @@ int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
|
|
return 0;
|
|
}
|
|
|
|
+struct vfio_devices {
|
|
+ struct vfio_device **devices;
|
|
+ int cur_index;
|
|
+ int max_index;
|
|
+};
|
|
+
|
|
static long vfio_pci_ioctl(void *device_data,
|
|
unsigned int cmd, unsigned long arg)
|
|
{
|
|
@@ -761,7 +769,7 @@ static long vfio_pci_ioctl(void *device_data,
|
|
{
|
|
void __iomem *io;
|
|
size_t size;
|
|
- u16 orig_cmd;
|
|
+ u16 cmd;
|
|
|
|
info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
|
|
info.flags = 0;
|
|
@@ -781,10 +789,7 @@ static long vfio_pci_ioctl(void *device_data,
|
|
* Is it really there? Enable memory decode for
|
|
* implicit access in pci_map_rom().
|
|
*/
|
|
- pci_read_config_word(pdev, PCI_COMMAND, &orig_cmd);
|
|
- pci_write_config_word(pdev, PCI_COMMAND,
|
|
- orig_cmd | PCI_COMMAND_MEMORY);
|
|
-
|
|
+ cmd = vfio_pci_memory_lock_and_enable(vdev);
|
|
io = pci_map_rom(pdev, &size);
|
|
if (io) {
|
|
info.flags = VFIO_REGION_INFO_FLAG_READ;
|
|
@@ -792,8 +797,8 @@ static long vfio_pci_ioctl(void *device_data,
|
|
} else {
|
|
info.size = 0;
|
|
}
|
|
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
|
|
|
|
- pci_write_config_word(pdev, PCI_COMMAND, orig_cmd);
|
|
break;
|
|
}
|
|
case VFIO_PCI_VGA_REGION_INDEX:
|
|
@@ -936,8 +941,16 @@ static long vfio_pci_ioctl(void *device_data,
|
|
return ret;
|
|
|
|
} else if (cmd == VFIO_DEVICE_RESET) {
|
|
- return vdev->reset_works ?
|
|
- pci_try_reset_function(vdev->pdev) : -EINVAL;
|
|
+ int ret;
|
|
+
|
|
+ if (!vdev->reset_works)
|
|
+ return -EINVAL;
|
|
+
|
|
+ vfio_pci_zap_and_down_write_memory_lock(vdev);
|
|
+ ret = pci_try_reset_function(vdev->pdev);
|
|
+ up_write(&vdev->memory_lock);
|
|
+
|
|
+ return ret;
|
|
|
|
} else if (cmd == VFIO_DEVICE_GET_PCI_HOT_RESET_INFO) {
|
|
struct vfio_pci_hot_reset_info hdr;
|
|
@@ -1017,8 +1030,9 @@ reset_info_exit:
|
|
int32_t *group_fds;
|
|
struct vfio_pci_group_entry *groups;
|
|
struct vfio_pci_group_info info;
|
|
+ struct vfio_devices devs = { .cur_index = 0 };
|
|
bool slot = false;
|
|
- int i, count = 0, ret = 0;
|
|
+ int i, group_idx, mem_idx = 0, count = 0, ret = 0;
|
|
|
|
minsz = offsetofend(struct vfio_pci_hot_reset, count);
|
|
|
|
@@ -1070,9 +1084,9 @@ reset_info_exit:
|
|
* user interface and store the group and iommu ID. This
|
|
* ensures the group is held across the reset.
|
|
*/
|
|
- for (i = 0; i < hdr.count; i++) {
|
|
+ for (group_idx = 0; group_idx < hdr.count; group_idx++) {
|
|
struct vfio_group *group;
|
|
- struct fd f = fdget(group_fds[i]);
|
|
+ struct fd f = fdget(group_fds[group_idx]);
|
|
if (!f.file) {
|
|
ret = -EBADF;
|
|
break;
|
|
@@ -1085,8 +1099,9 @@ reset_info_exit:
|
|
break;
|
|
}
|
|
|
|
- groups[i].group = group;
|
|
- groups[i].id = vfio_external_user_iommu_id(group);
|
|
+ groups[group_idx].group = group;
|
|
+ groups[group_idx].id =
|
|
+ vfio_external_user_iommu_id(group);
|
|
}
|
|
|
|
kfree(group_fds);
|
|
@@ -1105,13 +1120,63 @@ reset_info_exit:
|
|
ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
|
|
vfio_pci_validate_devs,
|
|
&info, slot);
|
|
- if (!ret)
|
|
- /* User has access, do the reset */
|
|
- ret = pci_reset_bus(vdev->pdev);
|
|
+ if (ret)
|
|
+ goto hot_reset_release;
|
|
+
|
|
+ devs.max_index = count;
|
|
+ devs.devices = kcalloc(count, sizeof(struct vfio_device *),
|
|
+ GFP_KERNEL);
|
|
+ if (!devs.devices) {
|
|
+ ret = -ENOMEM;
|
|
+ goto hot_reset_release;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * We need to get memory_lock for each device, but devices
|
|
+ * can share mmap_sem, therefore we need to zap and hold
|
|
+ * the vma_lock for each device, and only then get each
|
|
+ * memory_lock.
|
|
+ */
|
|
+ ret = vfio_pci_for_each_slot_or_bus(vdev->pdev,
|
|
+ vfio_pci_try_zap_and_vma_lock_cb,
|
|
+ &devs, slot);
|
|
+ if (ret)
|
|
+ goto hot_reset_release;
|
|
+
|
|
+ for (; mem_idx < devs.cur_index; mem_idx++) {
|
|
+ struct vfio_pci_device *tmp;
|
|
+
|
|
+ tmp = vfio_device_data(devs.devices[mem_idx]);
|
|
+
|
|
+ ret = down_write_trylock(&tmp->memory_lock);
|
|
+ if (!ret) {
|
|
+ ret = -EBUSY;
|
|
+ goto hot_reset_release;
|
|
+ }
|
|
+ mutex_unlock(&tmp->vma_lock);
|
|
+ }
|
|
+
|
|
+ /* User has access, do the reset */
|
|
+ ret = pci_reset_bus(vdev->pdev);
|
|
|
|
hot_reset_release:
|
|
- for (i--; i >= 0; i--)
|
|
- vfio_group_put_external_user(groups[i].group);
|
|
+ for (i = 0; i < devs.cur_index; i++) {
|
|
+ struct vfio_device *device;
|
|
+ struct vfio_pci_device *tmp;
|
|
+
|
|
+ device = devs.devices[i];
|
|
+ tmp = vfio_device_data(device);
|
|
+
|
|
+ if (i < mem_idx)
|
|
+ up_write(&tmp->memory_lock);
|
|
+ else
|
|
+ mutex_unlock(&tmp->vma_lock);
|
|
+ vfio_device_put(device);
|
|
+ }
|
|
+ kfree(devs.devices);
|
|
+
|
|
+ for (group_idx--; group_idx >= 0; group_idx--)
|
|
+ vfio_group_put_external_user(groups[group_idx].group);
|
|
|
|
kfree(groups);
|
|
return ret;
|
|
@@ -1192,6 +1257,202 @@ static ssize_t vfio_pci_write(void *device_data, const char __user *buf,
|
|
return vfio_pci_rw(device_data, (char __user *)buf, count, ppos, true);
|
|
}
|
|
|
|
+/* Return 1 on zap and vma_lock acquired, 0 on contention (only with @try) */
|
|
+static int vfio_pci_zap_and_vma_lock(struct vfio_pci_device *vdev, bool try)
|
|
+{
|
|
+ struct vfio_pci_mmap_vma *mmap_vma, *tmp;
|
|
+
|
|
+ /*
|
|
+ * Lock ordering:
|
|
+ * vma_lock is nested under mmap_sem for vm_ops callback paths.
|
|
+ * The memory_lock semaphore is used by both code paths calling
|
|
+ * into this function to zap vmas and the vm_ops.fault callback
|
|
+ * to protect the memory enable state of the device.
|
|
+ *
|
|
+ * When zapping vmas we need to maintain the mmap_sem => vma_lock
|
|
+ * ordering, which requires using vma_lock to walk vma_list to
|
|
+ * acquire an mm, then dropping vma_lock to get the mmap_sem and
|
|
+ * reacquiring vma_lock. This logic is derived from similar
|
|
+ * requirements in uverbs_user_mmap_disassociate().
|
|
+ *
|
|
+ * mmap_sem must always be the top-level lock when it is taken.
|
|
+ * Therefore we can only hold the memory_lock write lock when
|
|
+ * vma_list is empty, as we'd need to take mmap_sem to clear
|
|
+ * entries. vma_list can only be guaranteed empty when holding
|
|
+ * vma_lock, thus memory_lock is nested under vma_lock.
|
|
+ *
|
|
+ * This enables the vm_ops.fault callback to acquire vma_lock,
|
|
+ * followed by memory_lock read lock, while already holding
|
|
+ * mmap_sem without risk of deadlock.
|
|
+ */
|
|
+ while (1) {
|
|
+ struct mm_struct *mm = NULL;
|
|
+
|
|
+ if (try) {
|
|
+ if (!mutex_trylock(&vdev->vma_lock))
|
|
+ return 0;
|
|
+ } else {
|
|
+ mutex_lock(&vdev->vma_lock);
|
|
+ }
|
|
+ while (!list_empty(&vdev->vma_list)) {
|
|
+ mmap_vma = list_first_entry(&vdev->vma_list,
|
|
+ struct vfio_pci_mmap_vma,
|
|
+ vma_next);
|
|
+ mm = mmap_vma->vma->vm_mm;
|
|
+ if (mmget_not_zero(mm))
|
|
+ break;
|
|
+
|
|
+ list_del(&mmap_vma->vma_next);
|
|
+ kfree(mmap_vma);
|
|
+ mm = NULL;
|
|
+ }
|
|
+ if (!mm)
|
|
+ return 1;
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
+
|
|
+ if (try) {
|
|
+ if (!down_read_trylock(&mm->mmap_sem)) {
|
|
+ mmput(mm);
|
|
+ return 0;
|
|
+ }
|
|
+ } else {
|
|
+ down_read(&mm->mmap_sem);
|
|
+ }
|
|
+ if (mmget_still_valid(mm)) {
|
|
+ if (try) {
|
|
+ if (!mutex_trylock(&vdev->vma_lock)) {
|
|
+ up_read(&mm->mmap_sem);
|
|
+ mmput(mm);
|
|
+ return 0;
|
|
+ }
|
|
+ } else {
|
|
+ mutex_lock(&vdev->vma_lock);
|
|
+ }
|
|
+ list_for_each_entry_safe(mmap_vma, tmp,
|
|
+ &vdev->vma_list, vma_next) {
|
|
+ struct vm_area_struct *vma = mmap_vma->vma;
|
|
+
|
|
+ if (vma->vm_mm != mm)
|
|
+ continue;
|
|
+
|
|
+ list_del(&mmap_vma->vma_next);
|
|
+ kfree(mmap_vma);
|
|
+
|
|
+ zap_vma_ptes(vma, vma->vm_start,
|
|
+ vma->vm_end - vma->vm_start);
|
|
+ }
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
+ }
|
|
+ up_read(&mm->mmap_sem);
|
|
+ mmput(mm);
|
|
+ }
|
|
+}
|
|
+
|
|
+void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_device *vdev)
|
|
+{
|
|
+ vfio_pci_zap_and_vma_lock(vdev, false);
|
|
+ down_write(&vdev->memory_lock);
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
+}
|
|
+
|
|
+u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_device *vdev)
|
|
+{
|
|
+ u16 cmd;
|
|
+
|
|
+ down_write(&vdev->memory_lock);
|
|
+ pci_read_config_word(vdev->pdev, PCI_COMMAND, &cmd);
|
|
+ if (!(cmd & PCI_COMMAND_MEMORY))
|
|
+ pci_write_config_word(vdev->pdev, PCI_COMMAND,
|
|
+ cmd | PCI_COMMAND_MEMORY);
|
|
+
|
|
+ return cmd;
|
|
+}
|
|
+
|
|
+void vfio_pci_memory_unlock_and_restore(struct vfio_pci_device *vdev, u16 cmd)
|
|
+{
|
|
+ pci_write_config_word(vdev->pdev, PCI_COMMAND, cmd);
|
|
+ up_write(&vdev->memory_lock);
|
|
+}
|
|
+
|
|
+/* Caller holds vma_lock */
|
|
+static int __vfio_pci_add_vma(struct vfio_pci_device *vdev,
|
|
+ struct vm_area_struct *vma)
|
|
+{
|
|
+ struct vfio_pci_mmap_vma *mmap_vma;
|
|
+
|
|
+ mmap_vma = kmalloc(sizeof(*mmap_vma), GFP_KERNEL);
|
|
+ if (!mmap_vma)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ mmap_vma->vma = vma;
|
|
+ list_add(&mmap_vma->vma_next, &vdev->vma_list);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Zap mmaps on open so that we can fault them in on access and therefore
|
|
+ * our vma_list only tracks mappings accessed since last zap.
|
|
+ */
|
|
+static void vfio_pci_mmap_open(struct vm_area_struct *vma)
|
|
+{
|
|
+ zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
|
|
+}
|
|
+
|
|
+static void vfio_pci_mmap_close(struct vm_area_struct *vma)
|
|
+{
|
|
+ struct vfio_pci_device *vdev = vma->vm_private_data;
|
|
+ struct vfio_pci_mmap_vma *mmap_vma;
|
|
+
|
|
+ mutex_lock(&vdev->vma_lock);
|
|
+ list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) {
|
|
+ if (mmap_vma->vma == vma) {
|
|
+ list_del(&mmap_vma->vma_next);
|
|
+ kfree(mmap_vma);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
+}
|
|
+
|
|
+static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf)
|
|
+{
|
|
+ struct vm_area_struct *vma = vmf->vma;
|
|
+ struct vfio_pci_device *vdev = vma->vm_private_data;
|
|
+ vm_fault_t ret = VM_FAULT_NOPAGE;
|
|
+
|
|
+ mutex_lock(&vdev->vma_lock);
|
|
+ down_read(&vdev->memory_lock);
|
|
+
|
|
+ if (!__vfio_pci_memory_enabled(vdev)) {
|
|
+ ret = VM_FAULT_SIGBUS;
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
+ goto up_out;
|
|
+ }
|
|
+
|
|
+ if (__vfio_pci_add_vma(vdev, vma)) {
|
|
+ ret = VM_FAULT_OOM;
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
+ goto up_out;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
+
|
|
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
|
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
|
|
+ ret = VM_FAULT_SIGBUS;
|
|
+
|
|
+up_out:
|
|
+ up_read(&vdev->memory_lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct vm_operations_struct vfio_pci_mmap_ops = {
|
|
+ .open = vfio_pci_mmap_open,
|
|
+ .close = vfio_pci_mmap_close,
|
|
+ .fault = vfio_pci_mmap_fault,
|
|
+};
|
|
+
|
|
static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
|
|
{
|
|
struct vfio_pci_device *vdev = device_data;
|
|
@@ -1250,8 +1511,14 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
|
|
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
|
vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff;
|
|
|
|
- return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
|
- req_len, vma->vm_page_prot);
|
|
+ /*
|
|
+ * See remap_pfn_range(), called from vfio_pci_fault() but we can't
|
|
+ * change vm_flags within the fault handler. Set them now.
|
|
+ */
|
|
+ vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
|
|
+ vma->vm_ops = &vfio_pci_mmap_ops;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static void vfio_pci_request(void *device_data, unsigned int count)
|
|
@@ -1327,6 +1594,9 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
spin_lock_init(&vdev->irqlock);
|
|
mutex_init(&vdev->ioeventfds_lock);
|
|
INIT_LIST_HEAD(&vdev->ioeventfds_list);
|
|
+ mutex_init(&vdev->vma_lock);
|
|
+ INIT_LIST_HEAD(&vdev->vma_list);
|
|
+ init_rwsem(&vdev->memory_lock);
|
|
|
|
ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
|
|
if (ret) {
|
|
@@ -1516,12 +1786,6 @@ static void vfio_pci_reflck_put(struct vfio_pci_reflck *reflck)
|
|
kref_put_mutex(&reflck->kref, vfio_pci_reflck_release, &reflck_lock);
|
|
}
|
|
|
|
-struct vfio_devices {
|
|
- struct vfio_device **devices;
|
|
- int cur_index;
|
|
- int max_index;
|
|
-};
|
|
-
|
|
static int vfio_pci_get_unused_devs(struct pci_dev *pdev, void *data)
|
|
{
|
|
struct vfio_devices *devs = data;
|
|
@@ -1552,6 +1816,39 @@ static int vfio_pci_get_unused_devs(struct pci_dev *pdev, void *data)
|
|
return 0;
|
|
}
|
|
|
|
+static int vfio_pci_try_zap_and_vma_lock_cb(struct pci_dev *pdev, void *data)
|
|
+{
|
|
+ struct vfio_devices *devs = data;
|
|
+ struct vfio_device *device;
|
|
+ struct vfio_pci_device *vdev;
|
|
+
|
|
+ if (devs->cur_index == devs->max_index)
|
|
+ return -ENOSPC;
|
|
+
|
|
+ device = vfio_device_get_from_dev(&pdev->dev);
|
|
+ if (!device)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (pci_dev_driver(pdev) != &vfio_pci_driver) {
|
|
+ vfio_device_put(device);
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
+ vdev = vfio_device_data(device);
|
|
+
|
|
+ /*
|
|
+ * Locking multiple devices is prone to deadlock, runaway and
|
|
+ * unwind if we hit contention.
|
|
+ */
|
|
+ if (!vfio_pci_zap_and_vma_lock(vdev, true)) {
|
|
+ vfio_device_put(device);
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
+ devs->devices[devs->cur_index++] = device;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* If a bus or slot reset is available for the provided device and:
|
|
* - All of the devices affected by that bus or slot reset are unused
|
|
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
|
|
index d6359c37c9e55..927b608461c82 100644
|
|
--- a/drivers/vfio/pci/vfio_pci_config.c
|
|
+++ b/drivers/vfio/pci/vfio_pci_config.c
|
|
@@ -395,6 +395,20 @@ static inline void p_setd(struct perm_bits *p, int off, u32 virt, u32 write)
|
|
*(__le32 *)(&p->write[off]) = cpu_to_le32(write);
|
|
}
|
|
|
|
+/* Caller should hold memory_lock semaphore */
|
|
+bool __vfio_pci_memory_enabled(struct vfio_pci_device *vdev)
|
|
+{
|
|
+ struct pci_dev *pdev = vdev->pdev;
|
|
+ u16 cmd = le16_to_cpu(*(__le16 *)&vdev->vconfig[PCI_COMMAND]);
|
|
+
|
|
+ /*
|
|
+ * SR-IOV VF memory enable is handled by the MSE bit in the
|
|
+ * PF SR-IOV capability, there's therefore no need to trigger
|
|
+ * faults based on the virtual value.
|
|
+ */
|
|
+ return pdev->is_virtfn || (cmd & PCI_COMMAND_MEMORY);
|
|
+}
|
|
+
|
|
/*
|
|
* Restore the *real* BARs after we detect a FLR or backdoor reset.
|
|
* (backdoor = some device specific technique that we didn't catch)
|
|
@@ -554,13 +568,18 @@ static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos,
|
|
|
|
new_cmd = le32_to_cpu(val);
|
|
|
|
+ phys_io = !!(phys_cmd & PCI_COMMAND_IO);
|
|
+ virt_io = !!(le16_to_cpu(*virt_cmd) & PCI_COMMAND_IO);
|
|
+ new_io = !!(new_cmd & PCI_COMMAND_IO);
|
|
+
|
|
phys_mem = !!(phys_cmd & PCI_COMMAND_MEMORY);
|
|
virt_mem = !!(le16_to_cpu(*virt_cmd) & PCI_COMMAND_MEMORY);
|
|
new_mem = !!(new_cmd & PCI_COMMAND_MEMORY);
|
|
|
|
- phys_io = !!(phys_cmd & PCI_COMMAND_IO);
|
|
- virt_io = !!(le16_to_cpu(*virt_cmd) & PCI_COMMAND_IO);
|
|
- new_io = !!(new_cmd & PCI_COMMAND_IO);
|
|
+ if (!new_mem)
|
|
+ vfio_pci_zap_and_down_write_memory_lock(vdev);
|
|
+ else
|
|
+ down_write(&vdev->memory_lock);
|
|
|
|
/*
|
|
* If the user is writing mem/io enable (new_mem/io) and we
|
|
@@ -577,8 +596,11 @@ static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos,
|
|
}
|
|
|
|
count = vfio_default_config_write(vdev, pos, count, perm, offset, val);
|
|
- if (count < 0)
|
|
+ if (count < 0) {
|
|
+ if (offset == PCI_COMMAND)
|
|
+ up_write(&vdev->memory_lock);
|
|
return count;
|
|
+ }
|
|
|
|
/*
|
|
* Save current memory/io enable bits in vconfig to allow for
|
|
@@ -589,6 +611,8 @@ static int vfio_basic_config_write(struct vfio_pci_device *vdev, int pos,
|
|
|
|
*virt_cmd &= cpu_to_le16(~mask);
|
|
*virt_cmd |= cpu_to_le16(new_cmd & mask);
|
|
+
|
|
+ up_write(&vdev->memory_lock);
|
|
}
|
|
|
|
/* Emulate INTx disable */
|
|
@@ -826,8 +850,11 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos,
|
|
pos - offset + PCI_EXP_DEVCAP,
|
|
&cap);
|
|
|
|
- if (!ret && (cap & PCI_EXP_DEVCAP_FLR))
|
|
+ if (!ret && (cap & PCI_EXP_DEVCAP_FLR)) {
|
|
+ vfio_pci_zap_and_down_write_memory_lock(vdev);
|
|
pci_try_reset_function(vdev->pdev);
|
|
+ up_write(&vdev->memory_lock);
|
|
+ }
|
|
}
|
|
|
|
/*
|
|
@@ -905,8 +932,11 @@ static int vfio_af_config_write(struct vfio_pci_device *vdev, int pos,
|
|
pos - offset + PCI_AF_CAP,
|
|
&cap);
|
|
|
|
- if (!ret && (cap & PCI_AF_CAP_FLR) && (cap & PCI_AF_CAP_TP))
|
|
+ if (!ret && (cap & PCI_AF_CAP_FLR) && (cap & PCI_AF_CAP_TP)) {
|
|
+ vfio_pci_zap_and_down_write_memory_lock(vdev);
|
|
pci_try_reset_function(vdev->pdev);
|
|
+ up_write(&vdev->memory_lock);
|
|
+ }
|
|
}
|
|
|
|
return count;
|
|
@@ -1702,6 +1732,15 @@ int vfio_config_init(struct vfio_pci_device *vdev)
|
|
vconfig[PCI_INTERRUPT_PIN]);
|
|
|
|
vconfig[PCI_INTERRUPT_PIN] = 0; /* Gratuitous for good VFs */
|
|
+
|
|
+ /*
|
|
+ * VFs do no implement the memory enable bit of the COMMAND
|
|
+ * register therefore we'll not have it set in our initial
|
|
+ * copy of config space after pci_enable_device(). For
|
|
+ * consistency with PFs, set the virtual enable bit here.
|
|
+ */
|
|
+ *(__le16 *)&vconfig[PCI_COMMAND] |=
|
|
+ cpu_to_le16(PCI_COMMAND_MEMORY);
|
|
}
|
|
|
|
if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx)
|
|
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
|
|
index 2056f3f85f59b..1d9fb25929459 100644
|
|
--- a/drivers/vfio/pci/vfio_pci_intrs.c
|
|
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
|
|
@@ -249,6 +249,7 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
|
|
struct pci_dev *pdev = vdev->pdev;
|
|
unsigned int flag = msix ? PCI_IRQ_MSIX : PCI_IRQ_MSI;
|
|
int ret;
|
|
+ u16 cmd;
|
|
|
|
if (!is_irq_none(vdev))
|
|
return -EINVAL;
|
|
@@ -258,13 +259,16 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
|
|
return -ENOMEM;
|
|
|
|
/* return the number of supported vectors if we can't get all: */
|
|
+ cmd = vfio_pci_memory_lock_and_enable(vdev);
|
|
ret = pci_alloc_irq_vectors(pdev, 1, nvec, flag);
|
|
if (ret < nvec) {
|
|
if (ret > 0)
|
|
pci_free_irq_vectors(pdev);
|
|
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
|
|
kfree(vdev->ctx);
|
|
return ret;
|
|
}
|
|
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
|
|
|
|
vdev->num_ctx = nvec;
|
|
vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX :
|
|
@@ -287,6 +291,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
|
|
struct pci_dev *pdev = vdev->pdev;
|
|
struct eventfd_ctx *trigger;
|
|
int irq, ret;
|
|
+ u16 cmd;
|
|
|
|
if (vector < 0 || vector >= vdev->num_ctx)
|
|
return -EINVAL;
|
|
@@ -295,7 +300,11 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
|
|
|
|
if (vdev->ctx[vector].trigger) {
|
|
irq_bypass_unregister_producer(&vdev->ctx[vector].producer);
|
|
+
|
|
+ cmd = vfio_pci_memory_lock_and_enable(vdev);
|
|
free_irq(irq, vdev->ctx[vector].trigger);
|
|
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
|
|
+
|
|
kfree(vdev->ctx[vector].name);
|
|
eventfd_ctx_put(vdev->ctx[vector].trigger);
|
|
vdev->ctx[vector].trigger = NULL;
|
|
@@ -323,6 +332,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
|
|
* such a reset it would be unsuccessful. To avoid this, restore the
|
|
* cached value of the message prior to enabling.
|
|
*/
|
|
+ cmd = vfio_pci_memory_lock_and_enable(vdev);
|
|
if (msix) {
|
|
struct msi_msg msg;
|
|
|
|
@@ -332,6 +342,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
|
|
|
|
ret = request_irq(irq, vfio_msihandler, 0,
|
|
vdev->ctx[vector].name, trigger);
|
|
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
|
|
if (ret) {
|
|
kfree(vdev->ctx[vector].name);
|
|
eventfd_ctx_put(trigger);
|
|
@@ -376,6 +387,7 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
|
|
{
|
|
struct pci_dev *pdev = vdev->pdev;
|
|
int i;
|
|
+ u16 cmd;
|
|
|
|
for (i = 0; i < vdev->num_ctx; i++) {
|
|
vfio_virqfd_disable(&vdev->ctx[i].unmask);
|
|
@@ -384,7 +396,9 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
|
|
|
|
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
|
|
|
|
+ cmd = vfio_pci_memory_lock_and_enable(vdev);
|
|
pci_free_irq_vectors(pdev);
|
|
+ vfio_pci_memory_unlock_and_restore(vdev, cmd);
|
|
|
|
/*
|
|
* Both disable paths above use pci_intx_for_msi() to clear DisINTx
|
|
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
|
|
index ee6ee91718a4d..987b4d311fde9 100644
|
|
--- a/drivers/vfio/pci/vfio_pci_private.h
|
|
+++ b/drivers/vfio/pci/vfio_pci_private.h
|
|
@@ -84,6 +84,11 @@ struct vfio_pci_reflck {
|
|
struct mutex lock;
|
|
};
|
|
|
|
+struct vfio_pci_mmap_vma {
|
|
+ struct vm_area_struct *vma;
|
|
+ struct list_head vma_next;
|
|
+};
|
|
+
|
|
struct vfio_pci_device {
|
|
struct pci_dev *pdev;
|
|
void __iomem *barmap[PCI_STD_RESOURCE_END + 1];
|
|
@@ -122,6 +127,9 @@ struct vfio_pci_device {
|
|
struct list_head dummy_resources_list;
|
|
struct mutex ioeventfds_lock;
|
|
struct list_head ioeventfds_list;
|
|
+ struct mutex vma_lock;
|
|
+ struct list_head vma_list;
|
|
+ struct rw_semaphore memory_lock;
|
|
};
|
|
|
|
#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX)
|
|
@@ -164,6 +172,13 @@ extern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
|
|
extern int vfio_pci_set_power_state(struct vfio_pci_device *vdev,
|
|
pci_power_t state);
|
|
|
|
+extern bool __vfio_pci_memory_enabled(struct vfio_pci_device *vdev);
|
|
+extern void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_device
|
|
+ *vdev);
|
|
+extern u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_device *vdev);
|
|
+extern void vfio_pci_memory_unlock_and_restore(struct vfio_pci_device *vdev,
|
|
+ u16 cmd);
|
|
+
|
|
#ifdef CONFIG_VFIO_PCI_IGD
|
|
extern int vfio_pci_igd_init(struct vfio_pci_device *vdev);
|
|
#else
|
|
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
|
|
index 0120d8324a402..83f81d24df78e 100644
|
|
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
|
|
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
|
|
@@ -162,6 +162,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
|
|
size_t x_start = 0, x_end = 0;
|
|
resource_size_t end;
|
|
void __iomem *io;
|
|
+ struct resource *res = &vdev->pdev->resource[bar];
|
|
ssize_t done;
|
|
|
|
if (pci_resource_start(pdev, bar))
|
|
@@ -177,6 +178,14 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
|
|
|
|
count = min(count, (size_t)(end - pos));
|
|
|
|
+ if (res->flags & IORESOURCE_MEM) {
|
|
+ down_read(&vdev->memory_lock);
|
|
+ if (!__vfio_pci_memory_enabled(vdev)) {
|
|
+ up_read(&vdev->memory_lock);
|
|
+ return -EIO;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (bar == PCI_ROM_RESOURCE) {
|
|
/*
|
|
* The ROM can fill less space than the BAR, so we start the
|
|
@@ -184,13 +193,17 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
|
|
* filling large ROM BARs much faster.
|
|
*/
|
|
io = pci_map_rom(pdev, &x_start);
|
|
- if (!io)
|
|
- return -ENOMEM;
|
|
+ if (!io) {
|
|
+ done = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
x_end = end;
|
|
} else {
|
|
int ret = vfio_pci_setup_barmap(vdev, bar);
|
|
- if (ret)
|
|
- return ret;
|
|
+ if (ret) {
|
|
+ done = ret;
|
|
+ goto out;
|
|
+ }
|
|
|
|
io = vdev->barmap[bar];
|
|
}
|
|
@@ -207,6 +220,9 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
|
|
|
|
if (bar == PCI_ROM_RESOURCE)
|
|
pci_unmap_rom(pdev, io);
|
|
+out:
|
|
+ if (res->flags & IORESOURCE_MEM)
|
|
+ up_read(&vdev->memory_lock);
|
|
|
|
return done;
|
|
}
|
|
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
|
|
index ca8c10aa4a4bc..c6220f57fdf3e 100644
|
|
--- a/drivers/vfio/vfio_iommu_type1.c
|
|
+++ b/drivers/vfio/vfio_iommu_type1.c
|
|
@@ -335,6 +335,32 @@ static int put_pfn(unsigned long pfn, int prot)
|
|
return 0;
|
|
}
|
|
|
|
+static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm,
|
|
+ unsigned long vaddr, unsigned long *pfn,
|
|
+ bool write_fault)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = follow_pfn(vma, vaddr, pfn);
|
|
+ if (ret) {
|
|
+ bool unlocked = false;
|
|
+
|
|
+ ret = fixup_user_fault(NULL, mm, vaddr,
|
|
+ FAULT_FLAG_REMOTE |
|
|
+ (write_fault ? FAULT_FLAG_WRITE : 0),
|
|
+ &unlocked);
|
|
+ if (unlocked)
|
|
+ return -EAGAIN;
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = follow_pfn(vma, vaddr, pfn);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
|
|
int prot, unsigned long *pfn)
|
|
{
|
|
@@ -377,12 +403,16 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
|
|
|
|
vaddr = untagged_addr(vaddr);
|
|
|
|
+retry:
|
|
vma = find_vma_intersection(mm, vaddr, vaddr + 1);
|
|
|
|
if (vma && vma->vm_flags & VM_PFNMAP) {
|
|
- if (!follow_pfn(vma, vaddr, pfn) &&
|
|
- is_invalid_reserved_pfn(*pfn))
|
|
- ret = 0;
|
|
+ ret = follow_fault_pfn(vma, mm, vaddr, pfn, prot & IOMMU_WRITE);
|
|
+ if (ret == -EAGAIN)
|
|
+ goto retry;
|
|
+
|
|
+ if (!ret && !is_invalid_reserved_pfn(*pfn))
|
|
+ ret = -EFAULT;
|
|
}
|
|
|
|
up_read(&mm->mmap_sem);
|
|
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
|
|
index a38292ef79f6d..f38bdaea0ef11 100644
|
|
--- a/drivers/xen/xenbus/xenbus_client.c
|
|
+++ b/drivers/xen/xenbus/xenbus_client.c
|
|
@@ -363,8 +363,14 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr,
|
|
int i, j;
|
|
|
|
for (i = 0; i < nr_pages; i++) {
|
|
- err = gnttab_grant_foreign_access(dev->otherend_id,
|
|
- virt_to_gfn(vaddr), 0);
|
|
+ unsigned long gfn;
|
|
+
|
|
+ if (is_vmalloc_addr(vaddr))
|
|
+ gfn = pfn_to_gfn(vmalloc_to_pfn(vaddr));
|
|
+ else
|
|
+ gfn = virt_to_gfn(vaddr);
|
|
+
|
|
+ err = gnttab_grant_foreign_access(dev->otherend_id, gfn, 0);
|
|
if (err < 0) {
|
|
xenbus_dev_fatal(dev, err,
|
|
"granting access to ring page");
|
|
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
|
|
index f708c45d5f664..29f11e10a7c7d 100644
|
|
--- a/fs/affs/amigaffs.c
|
|
+++ b/fs/affs/amigaffs.c
|
|
@@ -420,24 +420,51 @@ affs_mode_to_prot(struct inode *inode)
|
|
u32 prot = AFFS_I(inode)->i_protect;
|
|
umode_t mode = inode->i_mode;
|
|
|
|
+ /*
|
|
+ * First, clear all RWED bits for owner, group, other.
|
|
+ * Then, recalculate them afresh.
|
|
+ *
|
|
+ * We'll always clear the delete-inhibit bit for the owner, as that is
|
|
+ * the classic single-user mode AmigaOS protection bit and we need to
|
|
+ * stay compatible with all scenarios.
|
|
+ *
|
|
+ * Since multi-user AmigaOS is an extension, we'll only set the
|
|
+ * delete-allow bit if any of the other bits in the same user class
|
|
+ * (group/other) are used.
|
|
+ */
|
|
+ prot &= ~(FIBF_NOEXECUTE | FIBF_NOREAD
|
|
+ | FIBF_NOWRITE | FIBF_NODELETE
|
|
+ | FIBF_GRP_EXECUTE | FIBF_GRP_READ
|
|
+ | FIBF_GRP_WRITE | FIBF_GRP_DELETE
|
|
+ | FIBF_OTR_EXECUTE | FIBF_OTR_READ
|
|
+ | FIBF_OTR_WRITE | FIBF_OTR_DELETE);
|
|
+
|
|
+ /* Classic single-user AmigaOS flags. These are inverted. */
|
|
if (!(mode & 0100))
|
|
prot |= FIBF_NOEXECUTE;
|
|
if (!(mode & 0400))
|
|
prot |= FIBF_NOREAD;
|
|
if (!(mode & 0200))
|
|
prot |= FIBF_NOWRITE;
|
|
+
|
|
+ /* Multi-user extended flags. Not inverted. */
|
|
if (mode & 0010)
|
|
prot |= FIBF_GRP_EXECUTE;
|
|
if (mode & 0040)
|
|
prot |= FIBF_GRP_READ;
|
|
if (mode & 0020)
|
|
prot |= FIBF_GRP_WRITE;
|
|
+ if (mode & 0070)
|
|
+ prot |= FIBF_GRP_DELETE;
|
|
+
|
|
if (mode & 0001)
|
|
prot |= FIBF_OTR_EXECUTE;
|
|
if (mode & 0004)
|
|
prot |= FIBF_OTR_READ;
|
|
if (mode & 0002)
|
|
prot |= FIBF_OTR_WRITE;
|
|
+ if (mode & 0007)
|
|
+ prot |= FIBF_OTR_DELETE;
|
|
|
|
AFFS_I(inode)->i_protect = prot;
|
|
}
|
|
diff --git a/fs/affs/file.c b/fs/affs/file.c
|
|
index a85817f54483f..ba084b0b214b9 100644
|
|
--- a/fs/affs/file.c
|
|
+++ b/fs/affs/file.c
|
|
@@ -428,6 +428,24 @@ static int affs_write_begin(struct file *file, struct address_space *mapping,
|
|
return ret;
|
|
}
|
|
|
|
+static int affs_write_end(struct file *file, struct address_space *mapping,
|
|
+ loff_t pos, unsigned int len, unsigned int copied,
|
|
+ struct page *page, void *fsdata)
|
|
+{
|
|
+ struct inode *inode = mapping->host;
|
|
+ int ret;
|
|
+
|
|
+ ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
|
|
+
|
|
+ /* Clear Archived bit on file writes, as AmigaOS would do */
|
|
+ if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
|
|
+ AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
|
|
+ mark_inode_dirty(inode);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
|
|
{
|
|
return generic_block_bmap(mapping,block,affs_get_block);
|
|
@@ -437,7 +455,7 @@ const struct address_space_operations affs_aops = {
|
|
.readpage = affs_readpage,
|
|
.writepage = affs_writepage,
|
|
.write_begin = affs_write_begin,
|
|
- .write_end = generic_write_end,
|
|
+ .write_end = affs_write_end,
|
|
.direct_IO = affs_direct_IO,
|
|
.bmap = _affs_bmap
|
|
};
|
|
@@ -794,6 +812,12 @@ done:
|
|
if (tmp > inode->i_size)
|
|
inode->i_size = AFFS_I(inode)->mmu_private = tmp;
|
|
|
|
+ /* Clear Archived bit on file writes, as AmigaOS would do */
|
|
+ if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
|
|
+ AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
|
|
+ mark_inode_dirty(inode);
|
|
+ }
|
|
+
|
|
err_first_bh:
|
|
unlock_page(page);
|
|
put_page(page);
|
|
diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c
|
|
index 02e976ca5732f..51ee3dd79700f 100644
|
|
--- a/fs/afs/fs_probe.c
|
|
+++ b/fs/afs/fs_probe.c
|
|
@@ -92,8 +92,8 @@ responded:
|
|
}
|
|
}
|
|
|
|
- rtt_us = rxrpc_kernel_get_srtt(call->net->socket, call->rxcall);
|
|
- if (rtt_us < server->probe.rtt) {
|
|
+ if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) &&
|
|
+ rtt_us < server->probe.rtt) {
|
|
server->probe.rtt = rtt_us;
|
|
alist->preferred = index;
|
|
have_result = true;
|
|
diff --git a/fs/afs/vl_probe.c b/fs/afs/vl_probe.c
|
|
index e3aa013c21779..081b7e5b13f58 100644
|
|
--- a/fs/afs/vl_probe.c
|
|
+++ b/fs/afs/vl_probe.c
|
|
@@ -92,8 +92,8 @@ responded:
|
|
}
|
|
}
|
|
|
|
- rtt_us = rxrpc_kernel_get_srtt(call->net->socket, call->rxcall);
|
|
- if (rtt_us < server->probe.rtt) {
|
|
+ if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) &&
|
|
+ rtt_us < server->probe.rtt) {
|
|
server->probe.rtt = rtt_us;
|
|
alist->preferred = index;
|
|
have_result = true;
|
|
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
|
|
index a989105d39c86..c05127f506373 100644
|
|
--- a/fs/btrfs/ctree.c
|
|
+++ b/fs/btrfs/ctree.c
|
|
@@ -1339,6 +1339,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
|
|
btrfs_tree_read_unlock_blocking(eb);
|
|
free_extent_buffer(eb);
|
|
|
|
+ btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb_rewin),
|
|
+ eb_rewin, btrfs_header_level(eb_rewin));
|
|
btrfs_tree_read_lock(eb_rewin);
|
|
__tree_mod_log_rewind(fs_info, eb_rewin, time_seq, tm);
|
|
WARN_ON(btrfs_header_nritems(eb_rewin) >
|
|
@@ -1412,7 +1414,6 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
|
|
|
|
if (!eb)
|
|
return NULL;
|
|
- btrfs_tree_read_lock(eb);
|
|
if (old_root) {
|
|
btrfs_set_header_bytenr(eb, eb->start);
|
|
btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV);
|
|
@@ -1420,6 +1421,9 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
|
|
btrfs_set_header_level(eb, old_root->level);
|
|
btrfs_set_header_generation(eb, old_generation);
|
|
}
|
|
+ btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb), eb,
|
|
+ btrfs_header_level(eb));
|
|
+ btrfs_tree_read_lock(eb);
|
|
if (tm)
|
|
__tree_mod_log_rewind(fs_info, eb, time_seq, tm);
|
|
else
|
|
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
|
|
index ef05cbacef73f..541497036cc24 100644
|
|
--- a/fs/btrfs/extent-tree.c
|
|
+++ b/fs/btrfs/extent-tree.c
|
|
@@ -4446,7 +4446,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
|
return ERR_PTR(-EUCLEAN);
|
|
}
|
|
|
|
- btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
|
|
+ btrfs_set_buffer_lockdep_class(owner, buf, level);
|
|
btrfs_tree_lock(buf);
|
|
btrfs_clean_tree_block(buf);
|
|
clear_bit(EXTENT_BUFFER_STALE, &buf->bflags);
|
|
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
|
|
index 5707bf0575d43..60c21cfb19480 100644
|
|
--- a/fs/btrfs/extent_io.c
|
|
+++ b/fs/btrfs/extent_io.c
|
|
@@ -5607,9 +5607,9 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
|
|
}
|
|
}
|
|
|
|
-int read_extent_buffer_to_user(const struct extent_buffer *eb,
|
|
- void __user *dstv,
|
|
- unsigned long start, unsigned long len)
|
|
+int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb,
|
|
+ void __user *dstv,
|
|
+ unsigned long start, unsigned long len)
|
|
{
|
|
size_t cur;
|
|
size_t offset;
|
|
@@ -5630,7 +5630,7 @@ int read_extent_buffer_to_user(const struct extent_buffer *eb,
|
|
|
|
cur = min(len, (PAGE_SIZE - offset));
|
|
kaddr = page_address(page);
|
|
- if (copy_to_user(dst, kaddr + offset, cur)) {
|
|
+ if (probe_user_write(dst, kaddr + offset, cur)) {
|
|
ret = -EFAULT;
|
|
break;
|
|
}
|
|
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
|
|
index cf3424d58fec7..bc858c8cef0a6 100644
|
|
--- a/fs/btrfs/extent_io.h
|
|
+++ b/fs/btrfs/extent_io.h
|
|
@@ -457,9 +457,9 @@ int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
|
|
void read_extent_buffer(const struct extent_buffer *eb, void *dst,
|
|
unsigned long start,
|
|
unsigned long len);
|
|
-int read_extent_buffer_to_user(const struct extent_buffer *eb,
|
|
- void __user *dst, unsigned long start,
|
|
- unsigned long len);
|
|
+int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb,
|
|
+ void __user *dst, unsigned long start,
|
|
+ unsigned long len);
|
|
void write_extent_buffer_fsid(struct extent_buffer *eb, const void *src);
|
|
void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb,
|
|
const void *src);
|
|
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
|
|
index 88745b5182126..775fd5975191b 100644
|
|
--- a/fs/btrfs/ioctl.c
|
|
+++ b/fs/btrfs/ioctl.c
|
|
@@ -2105,9 +2105,14 @@ static noinline int copy_to_sk(struct btrfs_path *path,
|
|
sh.len = item_len;
|
|
sh.transid = found_transid;
|
|
|
|
- /* copy search result header */
|
|
- if (copy_to_user(ubuf + *sk_offset, &sh, sizeof(sh))) {
|
|
- ret = -EFAULT;
|
|
+ /*
|
|
+ * Copy search result header. If we fault then loop again so we
|
|
+ * can fault in the pages and -EFAULT there if there's a
|
|
+ * problem. Otherwise we'll fault and then copy the buffer in
|
|
+ * properly this next time through
|
|
+ */
|
|
+ if (probe_user_write(ubuf + *sk_offset, &sh, sizeof(sh))) {
|
|
+ ret = 0;
|
|
goto out;
|
|
}
|
|
|
|
@@ -2115,10 +2120,14 @@ static noinline int copy_to_sk(struct btrfs_path *path,
|
|
|
|
if (item_len) {
|
|
char __user *up = ubuf + *sk_offset;
|
|
- /* copy the item */
|
|
- if (read_extent_buffer_to_user(leaf, up,
|
|
- item_off, item_len)) {
|
|
- ret = -EFAULT;
|
|
+ /*
|
|
+ * Copy the item, same behavior as above, but reset the
|
|
+ * * sk_offset so we copy the full thing again.
|
|
+ */
|
|
+ if (read_extent_buffer_to_user_nofault(leaf, up,
|
|
+ item_off, item_len)) {
|
|
+ ret = 0;
|
|
+ *sk_offset -= sizeof(sh);
|
|
goto out;
|
|
}
|
|
|
|
@@ -2206,6 +2215,10 @@ static noinline int search_ioctl(struct inode *inode,
|
|
key.offset = sk->min_offset;
|
|
|
|
while (1) {
|
|
+ ret = fault_in_pages_writeable(ubuf, *buf_size - sk_offset);
|
|
+ if (ret)
|
|
+ break;
|
|
+
|
|
ret = btrfs_search_forward(root, &key, path, sk->min_transid);
|
|
if (ret != 0) {
|
|
if (ret > 0)
|
|
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
|
|
index 498b824148187..93d7cb56e44b2 100644
|
|
--- a/fs/btrfs/scrub.c
|
|
+++ b/fs/btrfs/scrub.c
|
|
@@ -3742,50 +3742,84 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
|
|
return 0;
|
|
}
|
|
|
|
+static void scrub_workers_put(struct btrfs_fs_info *fs_info)
|
|
+{
|
|
+ if (refcount_dec_and_mutex_lock(&fs_info->scrub_workers_refcnt,
|
|
+ &fs_info->scrub_lock)) {
|
|
+ struct btrfs_workqueue *scrub_workers = NULL;
|
|
+ struct btrfs_workqueue *scrub_wr_comp = NULL;
|
|
+ struct btrfs_workqueue *scrub_parity = NULL;
|
|
+
|
|
+ scrub_workers = fs_info->scrub_workers;
|
|
+ scrub_wr_comp = fs_info->scrub_wr_completion_workers;
|
|
+ scrub_parity = fs_info->scrub_parity_workers;
|
|
+
|
|
+ fs_info->scrub_workers = NULL;
|
|
+ fs_info->scrub_wr_completion_workers = NULL;
|
|
+ fs_info->scrub_parity_workers = NULL;
|
|
+ mutex_unlock(&fs_info->scrub_lock);
|
|
+
|
|
+ btrfs_destroy_workqueue(scrub_workers);
|
|
+ btrfs_destroy_workqueue(scrub_wr_comp);
|
|
+ btrfs_destroy_workqueue(scrub_parity);
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
* get a reference count on fs_info->scrub_workers. start worker if necessary
|
|
*/
|
|
static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info,
|
|
int is_dev_replace)
|
|
{
|
|
+ struct btrfs_workqueue *scrub_workers = NULL;
|
|
+ struct btrfs_workqueue *scrub_wr_comp = NULL;
|
|
+ struct btrfs_workqueue *scrub_parity = NULL;
|
|
unsigned int flags = WQ_FREEZABLE | WQ_UNBOUND;
|
|
int max_active = fs_info->thread_pool_size;
|
|
+ int ret = -ENOMEM;
|
|
|
|
- lockdep_assert_held(&fs_info->scrub_lock);
|
|
+ if (refcount_inc_not_zero(&fs_info->scrub_workers_refcnt))
|
|
+ return 0;
|
|
|
|
- if (refcount_read(&fs_info->scrub_workers_refcnt) == 0) {
|
|
- ASSERT(fs_info->scrub_workers == NULL);
|
|
- fs_info->scrub_workers = btrfs_alloc_workqueue(fs_info, "scrub",
|
|
- flags, is_dev_replace ? 1 : max_active, 4);
|
|
- if (!fs_info->scrub_workers)
|
|
- goto fail_scrub_workers;
|
|
-
|
|
- ASSERT(fs_info->scrub_wr_completion_workers == NULL);
|
|
- fs_info->scrub_wr_completion_workers =
|
|
- btrfs_alloc_workqueue(fs_info, "scrubwrc", flags,
|
|
- max_active, 2);
|
|
- if (!fs_info->scrub_wr_completion_workers)
|
|
- goto fail_scrub_wr_completion_workers;
|
|
+ scrub_workers = btrfs_alloc_workqueue(fs_info, "scrub", flags,
|
|
+ is_dev_replace ? 1 : max_active, 4);
|
|
+ if (!scrub_workers)
|
|
+ goto fail_scrub_workers;
|
|
|
|
- ASSERT(fs_info->scrub_parity_workers == NULL);
|
|
- fs_info->scrub_parity_workers =
|
|
- btrfs_alloc_workqueue(fs_info, "scrubparity", flags,
|
|
+ scrub_wr_comp = btrfs_alloc_workqueue(fs_info, "scrubwrc", flags,
|
|
max_active, 2);
|
|
- if (!fs_info->scrub_parity_workers)
|
|
- goto fail_scrub_parity_workers;
|
|
+ if (!scrub_wr_comp)
|
|
+ goto fail_scrub_wr_completion_workers;
|
|
|
|
+ scrub_parity = btrfs_alloc_workqueue(fs_info, "scrubparity", flags,
|
|
+ max_active, 2);
|
|
+ if (!scrub_parity)
|
|
+ goto fail_scrub_parity_workers;
|
|
+
|
|
+ mutex_lock(&fs_info->scrub_lock);
|
|
+ if (refcount_read(&fs_info->scrub_workers_refcnt) == 0) {
|
|
+ ASSERT(fs_info->scrub_workers == NULL &&
|
|
+ fs_info->scrub_wr_completion_workers == NULL &&
|
|
+ fs_info->scrub_parity_workers == NULL);
|
|
+ fs_info->scrub_workers = scrub_workers;
|
|
+ fs_info->scrub_wr_completion_workers = scrub_wr_comp;
|
|
+ fs_info->scrub_parity_workers = scrub_parity;
|
|
refcount_set(&fs_info->scrub_workers_refcnt, 1);
|
|
- } else {
|
|
- refcount_inc(&fs_info->scrub_workers_refcnt);
|
|
+ mutex_unlock(&fs_info->scrub_lock);
|
|
+ return 0;
|
|
}
|
|
- return 0;
|
|
+ /* Other thread raced in and created the workers for us */
|
|
+ refcount_inc(&fs_info->scrub_workers_refcnt);
|
|
+ mutex_unlock(&fs_info->scrub_lock);
|
|
|
|
+ ret = 0;
|
|
+ btrfs_destroy_workqueue(scrub_parity);
|
|
fail_scrub_parity_workers:
|
|
- btrfs_destroy_workqueue(fs_info->scrub_wr_completion_workers);
|
|
+ btrfs_destroy_workqueue(scrub_wr_comp);
|
|
fail_scrub_wr_completion_workers:
|
|
- btrfs_destroy_workqueue(fs_info->scrub_workers);
|
|
+ btrfs_destroy_workqueue(scrub_workers);
|
|
fail_scrub_workers:
|
|
- return -ENOMEM;
|
|
+ return ret;
|
|
}
|
|
|
|
int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
|
|
@@ -3796,9 +3830,6 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
|
|
int ret;
|
|
struct btrfs_device *dev;
|
|
unsigned int nofs_flag;
|
|
- struct btrfs_workqueue *scrub_workers = NULL;
|
|
- struct btrfs_workqueue *scrub_wr_comp = NULL;
|
|
- struct btrfs_workqueue *scrub_parity = NULL;
|
|
|
|
if (btrfs_fs_closing(fs_info))
|
|
return -EAGAIN;
|
|
@@ -3845,13 +3876,17 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
|
|
if (IS_ERR(sctx))
|
|
return PTR_ERR(sctx);
|
|
|
|
+ ret = scrub_workers_get(fs_info, is_dev_replace);
|
|
+ if (ret)
|
|
+ goto out_free_ctx;
|
|
+
|
|
mutex_lock(&fs_info->fs_devices->device_list_mutex);
|
|
dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL, true);
|
|
if (!dev || (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) &&
|
|
!is_dev_replace)) {
|
|
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
|
ret = -ENODEV;
|
|
- goto out_free_ctx;
|
|
+ goto out;
|
|
}
|
|
|
|
if (!is_dev_replace && !readonly &&
|
|
@@ -3860,7 +3895,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
|
|
btrfs_err_in_rcu(fs_info, "scrub: device %s is not writable",
|
|
rcu_str_deref(dev->name));
|
|
ret = -EROFS;
|
|
- goto out_free_ctx;
|
|
+ goto out;
|
|
}
|
|
|
|
mutex_lock(&fs_info->scrub_lock);
|
|
@@ -3869,7 +3904,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
|
|
mutex_unlock(&fs_info->scrub_lock);
|
|
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
|
ret = -EIO;
|
|
- goto out_free_ctx;
|
|
+ goto out;
|
|
}
|
|
|
|
down_read(&fs_info->dev_replace.rwsem);
|
|
@@ -3880,17 +3915,10 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
|
|
mutex_unlock(&fs_info->scrub_lock);
|
|
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
|
ret = -EINPROGRESS;
|
|
- goto out_free_ctx;
|
|
+ goto out;
|
|
}
|
|
up_read(&fs_info->dev_replace.rwsem);
|
|
|
|
- ret = scrub_workers_get(fs_info, is_dev_replace);
|
|
- if (ret) {
|
|
- mutex_unlock(&fs_info->scrub_lock);
|
|
- mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
|
- goto out_free_ctx;
|
|
- }
|
|
-
|
|
sctx->readonly = readonly;
|
|
dev->scrub_ctx = sctx;
|
|
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
|
@@ -3943,24 +3971,14 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
|
|
|
|
mutex_lock(&fs_info->scrub_lock);
|
|
dev->scrub_ctx = NULL;
|
|
- if (refcount_dec_and_test(&fs_info->scrub_workers_refcnt)) {
|
|
- scrub_workers = fs_info->scrub_workers;
|
|
- scrub_wr_comp = fs_info->scrub_wr_completion_workers;
|
|
- scrub_parity = fs_info->scrub_parity_workers;
|
|
-
|
|
- fs_info->scrub_workers = NULL;
|
|
- fs_info->scrub_wr_completion_workers = NULL;
|
|
- fs_info->scrub_parity_workers = NULL;
|
|
- }
|
|
mutex_unlock(&fs_info->scrub_lock);
|
|
|
|
- btrfs_destroy_workqueue(scrub_workers);
|
|
- btrfs_destroy_workqueue(scrub_wr_comp);
|
|
- btrfs_destroy_workqueue(scrub_parity);
|
|
+ scrub_workers_put(fs_info);
|
|
scrub_put_ctx(sctx);
|
|
|
|
return ret;
|
|
-
|
|
+out:
|
|
+ scrub_workers_put(fs_info);
|
|
out_free_ctx:
|
|
scrub_free_ctx(sctx);
|
|
|
|
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
|
|
index 0e44db066641e..91ea38506fbb7 100644
|
|
--- a/fs/btrfs/tree-checker.c
|
|
+++ b/fs/btrfs/tree-checker.c
|
|
@@ -772,7 +772,7 @@ static int check_inode_item(struct extent_buffer *leaf,
|
|
/* Here we use super block generation + 1 to handle log tree */
|
|
if (btrfs_inode_generation(leaf, iitem) > super_gen + 1) {
|
|
inode_item_err(fs_info, leaf, slot,
|
|
- "invalid inode generation: has %llu expect (0, %llu]",
|
|
+ "invalid inode transid: has %llu expect [0, %llu]",
|
|
btrfs_inode_generation(leaf, iitem),
|
|
super_gen + 1);
|
|
return -EUCLEAN;
|
|
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
|
|
index 196ddbcd29360..81be71fb569e1 100644
|
|
--- a/fs/btrfs/volumes.c
|
|
+++ b/fs/btrfs/volumes.c
|
|
@@ -4568,6 +4568,7 @@ static int btrfs_uuid_scan_kthread(void *data)
|
|
goto skip;
|
|
}
|
|
update_tree:
|
|
+ btrfs_release_path(path);
|
|
if (!btrfs_is_empty_uuid(root_item.uuid)) {
|
|
ret = btrfs_uuid_tree_add(trans, root_item.uuid,
|
|
BTRFS_UUID_KEY_SUBVOL,
|
|
@@ -4592,6 +4593,7 @@ update_tree:
|
|
}
|
|
|
|
skip:
|
|
+ btrfs_release_path(path);
|
|
if (trans) {
|
|
ret = btrfs_end_transaction(trans);
|
|
trans = NULL;
|
|
@@ -4599,7 +4601,6 @@ skip:
|
|
break;
|
|
}
|
|
|
|
- btrfs_release_path(path);
|
|
if (key.offset < (u64)-1) {
|
|
key.offset++;
|
|
} else if (key.type < BTRFS_ROOT_ITEM_KEY) {
|
|
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
|
|
index 4a6b14a2bd7f9..a10711a6337af 100644
|
|
--- a/fs/ceph/file.c
|
|
+++ b/fs/ceph/file.c
|
|
@@ -2198,6 +2198,7 @@ const struct file_operations ceph_file_fops = {
|
|
.mmap = ceph_mmap,
|
|
.fsync = ceph_fsync,
|
|
.lock = ceph_lock,
|
|
+ .setlease = simple_nosetlease,
|
|
.flock = ceph_flock,
|
|
.splice_read = generic_file_splice_read,
|
|
.splice_write = iter_file_splice_write,
|
|
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
|
|
index 0d9b1e2b9da72..ae1d32344f7ac 100644
|
|
--- a/fs/eventpoll.c
|
|
+++ b/fs/eventpoll.c
|
|
@@ -1992,9 +1992,9 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
|
|
* during ep_insert().
|
|
*/
|
|
if (list_empty(&epi->ffd.file->f_tfile_llink)) {
|
|
- get_file(epi->ffd.file);
|
|
- list_add(&epi->ffd.file->f_tfile_llink,
|
|
- &tfile_check_list);
|
|
+ if (get_file_rcu(epi->ffd.file))
|
|
+ list_add(&epi->ffd.file->f_tfile_llink,
|
|
+ &tfile_check_list);
|
|
}
|
|
}
|
|
}
|
|
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
|
|
index 39c4772e96c9d..d73103cdda210 100644
|
|
--- a/fs/ext2/file.c
|
|
+++ b/fs/ext2/file.c
|
|
@@ -93,8 +93,10 @@ static vm_fault_t ext2_dax_fault(struct vm_fault *vmf)
|
|
struct inode *inode = file_inode(vmf->vma->vm_file);
|
|
struct ext2_inode_info *ei = EXT2_I(inode);
|
|
vm_fault_t ret;
|
|
+ bool write = (vmf->flags & FAULT_FLAG_WRITE) &&
|
|
+ (vmf->vma->vm_flags & VM_SHARED);
|
|
|
|
- if (vmf->flags & FAULT_FLAG_WRITE) {
|
|
+ if (write) {
|
|
sb_start_pagefault(inode->i_sb);
|
|
file_update_time(vmf->vma->vm_file);
|
|
}
|
|
@@ -103,7 +105,7 @@ static vm_fault_t ext2_dax_fault(struct vm_fault *vmf)
|
|
ret = dax_iomap_fault(vmf, PE_SIZE_PTE, NULL, NULL, &ext2_iomap_ops);
|
|
|
|
up_read(&ei->dax_sem);
|
|
- if (vmf->flags & FAULT_FLAG_WRITE)
|
|
+ if (write)
|
|
sb_end_pagefault(inode->i_sb);
|
|
return ret;
|
|
}
|
|
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
|
|
index f0089e862216c..fe277ee5ec7c4 100644
|
|
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
|
|
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
|
|
@@ -946,8 +946,10 @@ xfs_attr_shortform_verify(
|
|
* struct xfs_attr_sf_entry has a variable length.
|
|
* Check the fixed-offset parts of the structure are
|
|
* within the data buffer.
|
|
+ * xfs_attr_sf_entry is defined with a 1-byte variable
|
|
+ * array at the end, so we must subtract that off.
|
|
*/
|
|
- if (((char *)sfep + sizeof(*sfep)) >= endp)
|
|
+ if (((char *)sfep + sizeof(*sfep) - 1) >= endp)
|
|
return __this_address;
|
|
|
|
/* Don't allow names with known bad length. */
|
|
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
|
|
index 3f76da11197c4..19a600443b9ee 100644
|
|
--- a/fs/xfs/libxfs/xfs_bmap.c
|
|
+++ b/fs/xfs/libxfs/xfs_bmap.c
|
|
@@ -6179,7 +6179,7 @@ xfs_bmap_validate_extent(
|
|
|
|
isrt = XFS_IS_REALTIME_INODE(ip);
|
|
endfsb = irec->br_startblock + irec->br_blockcount - 1;
|
|
- if (isrt) {
|
|
+ if (isrt && whichfork == XFS_DATA_FORK) {
|
|
if (!xfs_verify_rtbno(mp, irec->br_startblock))
|
|
return __this_address;
|
|
if (!xfs_verify_rtbno(mp, endfsb))
|
|
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
|
|
index 1ffb179f35d23..1e2176190c86f 100644
|
|
--- a/fs/xfs/xfs_file.c
|
|
+++ b/fs/xfs/xfs_file.c
|
|
@@ -1172,6 +1172,14 @@ __xfs_filemap_fault(
|
|
return ret;
|
|
}
|
|
|
|
+static inline bool
|
|
+xfs_is_write_fault(
|
|
+ struct vm_fault *vmf)
|
|
+{
|
|
+ return (vmf->flags & FAULT_FLAG_WRITE) &&
|
|
+ (vmf->vma->vm_flags & VM_SHARED);
|
|
+}
|
|
+
|
|
static vm_fault_t
|
|
xfs_filemap_fault(
|
|
struct vm_fault *vmf)
|
|
@@ -1179,7 +1187,7 @@ xfs_filemap_fault(
|
|
/* DAX can shortcut the normal fault path on write faults! */
|
|
return __xfs_filemap_fault(vmf, PE_SIZE_PTE,
|
|
IS_DAX(file_inode(vmf->vma->vm_file)) &&
|
|
- (vmf->flags & FAULT_FLAG_WRITE));
|
|
+ xfs_is_write_fault(vmf));
|
|
}
|
|
|
|
static vm_fault_t
|
|
@@ -1192,7 +1200,7 @@ xfs_filemap_huge_fault(
|
|
|
|
/* DAX can shortcut the normal fault path on write faults! */
|
|
return __xfs_filemap_fault(vmf, pe_size,
|
|
- (vmf->flags & FAULT_FLAG_WRITE));
|
|
+ xfs_is_write_fault(vmf));
|
|
}
|
|
|
|
static vm_fault_t
|
|
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
|
|
index a032f01e928c5..d7a628e066ee8 100644
|
|
--- a/include/linux/bvec.h
|
|
+++ b/include/linux/bvec.h
|
|
@@ -110,11 +110,18 @@ static inline bool bvec_iter_advance(const struct bio_vec *bv,
|
|
return true;
|
|
}
|
|
|
|
+static inline void bvec_iter_skip_zero_bvec(struct bvec_iter *iter)
|
|
+{
|
|
+ iter->bi_bvec_done = 0;
|
|
+ iter->bi_idx++;
|
|
+}
|
|
+
|
|
#define for_each_bvec(bvl, bio_vec, iter, start) \
|
|
for (iter = (start); \
|
|
(iter).bi_size && \
|
|
((bvl = bvec_iter_bvec((bio_vec), (iter))), 1); \
|
|
- bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len))
|
|
+ (bvl).bv_len ? (void)bvec_iter_advance((bio_vec), &(iter), \
|
|
+ (bvl).bv_len) : bvec_iter_skip_zero_bvec(&(iter)))
|
|
|
|
/* for iterating one bio from start to end */
|
|
#define BVEC_ITER_ALL_INIT (struct bvec_iter) \
|
|
diff --git a/include/linux/libata.h b/include/linux/libata.h
|
|
index b9970f5bab67c..e752368ea3516 100644
|
|
--- a/include/linux/libata.h
|
|
+++ b/include/linux/libata.h
|
|
@@ -422,6 +422,7 @@ enum {
|
|
ATA_HORKAGE_NO_DMA_LOG = (1 << 23), /* don't use DMA for log read */
|
|
ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */
|
|
ATA_HORKAGE_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */
|
|
+ ATA_HORKAGE_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */
|
|
|
|
/* DMA mask for user DMA control: User visible values; DO NOT
|
|
renumber */
|
|
diff --git a/include/linux/log2.h b/include/linux/log2.h
|
|
index 83a4a3ca3e8a7..c619ec6eff4ae 100644
|
|
--- a/include/linux/log2.h
|
|
+++ b/include/linux/log2.h
|
|
@@ -173,7 +173,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
|
|
#define roundup_pow_of_two(n) \
|
|
( \
|
|
__builtin_constant_p(n) ? ( \
|
|
- (n == 1) ? 1 : \
|
|
+ ((n) == 1) ? 1 : \
|
|
(1UL << (ilog2((n) - 1) + 1)) \
|
|
) : \
|
|
__roundup_pow_of_two(n) \
|
|
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
|
|
index 851425c3178f1..89016d08f6a27 100644
|
|
--- a/include/linux/netfilter/nfnetlink.h
|
|
+++ b/include/linux/netfilter/nfnetlink.h
|
|
@@ -43,8 +43,7 @@ int nfnetlink_has_listeners(struct net *net, unsigned int group);
|
|
int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid,
|
|
unsigned int group, int echo, gfp_t flags);
|
|
int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error);
|
|
-int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid,
|
|
- int flags);
|
|
+int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid);
|
|
|
|
static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type)
|
|
{
|
|
diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h
|
|
index ab988940bf045..55b980b21f4b4 100644
|
|
--- a/include/net/af_rxrpc.h
|
|
+++ b/include/net/af_rxrpc.h
|
|
@@ -59,7 +59,7 @@ bool rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *,
|
|
void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *);
|
|
void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
|
|
struct sockaddr_rxrpc *);
|
|
-u32 rxrpc_kernel_get_srtt(struct socket *, struct rxrpc_call *);
|
|
+bool rxrpc_kernel_get_srtt(struct socket *, struct rxrpc_call *, u32 *);
|
|
int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
|
|
rxrpc_user_attach_call_t, unsigned long, gfp_t,
|
|
unsigned int);
|
|
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
|
|
index 2d0275f13bbfd..bc2c73f549622 100644
|
|
--- a/include/net/netfilter/nf_tables.h
|
|
+++ b/include/net/netfilter/nf_tables.h
|
|
@@ -143,6 +143,8 @@ static inline u64 nft_reg_load64(u32 *sreg)
|
|
static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
|
|
unsigned int len)
|
|
{
|
|
+ if (len % NFT_REG32_SIZE)
|
|
+ dst[len / NFT_REG32_SIZE] = 0;
|
|
memcpy(dst, src, len);
|
|
}
|
|
|
|
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
|
|
index ed8881ad18edd..0a995403172cc 100644
|
|
--- a/include/uapi/linux/netfilter/nf_tables.h
|
|
+++ b/include/uapi/linux/netfilter/nf_tables.h
|
|
@@ -132,7 +132,7 @@ enum nf_tables_msg_types {
|
|
* @NFTA_LIST_ELEM: list element (NLA_NESTED)
|
|
*/
|
|
enum nft_list_attributes {
|
|
- NFTA_LIST_UNPEC,
|
|
+ NFTA_LIST_UNSPEC,
|
|
NFTA_LIST_ELEM,
|
|
__NFTA_LIST_MAX
|
|
};
|
|
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
|
|
index 2a83b03c54a69..62ec514dae658 100644
|
|
--- a/mm/hugetlb.c
|
|
+++ b/mm/hugetlb.c
|
|
@@ -3082,6 +3082,22 @@ static unsigned int cpuset_mems_nr(unsigned int *array)
|
|
}
|
|
|
|
#ifdef CONFIG_SYSCTL
|
|
+static int proc_hugetlb_doulongvec_minmax(struct ctl_table *table, int write,
|
|
+ void *buffer, size_t *length,
|
|
+ loff_t *ppos, unsigned long *out)
|
|
+{
|
|
+ struct ctl_table dup_table;
|
|
+
|
|
+ /*
|
|
+ * In order to avoid races with __do_proc_doulongvec_minmax(), we
|
|
+ * can duplicate the @table and alter the duplicate of it.
|
|
+ */
|
|
+ dup_table = *table;
|
|
+ dup_table.data = out;
|
|
+
|
|
+ return proc_doulongvec_minmax(&dup_table, write, buffer, length, ppos);
|
|
+}
|
|
+
|
|
static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
|
|
struct ctl_table *table, int write,
|
|
void __user *buffer, size_t *length, loff_t *ppos)
|
|
@@ -3093,9 +3109,8 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
|
|
if (!hugepages_supported())
|
|
return -EOPNOTSUPP;
|
|
|
|
- table->data = &tmp;
|
|
- table->maxlen = sizeof(unsigned long);
|
|
- ret = proc_doulongvec_minmax(table, write, buffer, length, ppos);
|
|
+ ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos,
|
|
+ &tmp);
|
|
if (ret)
|
|
goto out;
|
|
|
|
@@ -3139,9 +3154,8 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
|
|
if (write && hstate_is_gigantic(h))
|
|
return -EINVAL;
|
|
|
|
- table->data = &tmp;
|
|
- table->maxlen = sizeof(unsigned long);
|
|
- ret = proc_doulongvec_minmax(table, write, buffer, length, ppos);
|
|
+ ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos,
|
|
+ &tmp);
|
|
if (ret)
|
|
goto out;
|
|
|
|
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
|
|
index 3623d1c5343f2..9ec618d5ea557 100644
|
|
--- a/mm/khugepaged.c
|
|
+++ b/mm/khugepaged.c
|
|
@@ -1592,7 +1592,7 @@ static void collapse_file(struct mm_struct *mm,
|
|
xas_unlock_irq(&xas);
|
|
page_cache_sync_readahead(mapping, &file->f_ra,
|
|
file, index,
|
|
- PAGE_SIZE);
|
|
+ end - index);
|
|
/* drain pagevecs to help isolate_lru_page() */
|
|
lru_add_drain();
|
|
page = find_lock_page(mapping, index);
|
|
diff --git a/mm/madvise.c b/mm/madvise.c
|
|
index d8cfc3a0c1534..26f7954865ed9 100644
|
|
--- a/mm/madvise.c
|
|
+++ b/mm/madvise.c
|
|
@@ -288,9 +288,9 @@ static long madvise_willneed(struct vm_area_struct *vma,
|
|
*/
|
|
*prev = NULL; /* tell sys_madvise we drop mmap_sem */
|
|
get_file(file);
|
|
- up_read(¤t->mm->mmap_sem);
|
|
offset = (loff_t)(start - vma->vm_start)
|
|
+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
|
|
+ up_read(¤t->mm->mmap_sem);
|
|
vfs_fadvise(file, offset, end - start, POSIX_FADV_WILLNEED);
|
|
fput(file);
|
|
down_read(¤t->mm->mmap_sem);
|
|
diff --git a/mm/slub.c b/mm/slub.c
|
|
index 709e31002504c..822ba07245291 100644
|
|
--- a/mm/slub.c
|
|
+++ b/mm/slub.c
|
|
@@ -645,12 +645,12 @@ static void slab_fix(struct kmem_cache *s, char *fmt, ...)
|
|
}
|
|
|
|
static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
|
|
- void *freelist, void *nextfree)
|
|
+ void **freelist, void *nextfree)
|
|
{
|
|
if ((s->flags & SLAB_CONSISTENCY_CHECKS) &&
|
|
- !check_valid_pointer(s, page, nextfree)) {
|
|
- object_err(s, page, freelist, "Freechain corrupt");
|
|
- freelist = NULL;
|
|
+ !check_valid_pointer(s, page, nextfree) && freelist) {
|
|
+ object_err(s, page, *freelist, "Freechain corrupt");
|
|
+ *freelist = NULL;
|
|
slab_fix(s, "Isolate corrupted freechain");
|
|
return true;
|
|
}
|
|
@@ -1394,7 +1394,7 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node,
|
|
int objects) {}
|
|
|
|
static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
|
|
- void *freelist, void *nextfree)
|
|
+ void **freelist, void *nextfree)
|
|
{
|
|
return false;
|
|
}
|
|
@@ -2086,7 +2086,7 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page,
|
|
* 'freelist' is already corrupted. So isolate all objects
|
|
* starting at 'freelist'.
|
|
*/
|
|
- if (freelist_corrupted(s, page, freelist, nextfree))
|
|
+ if (freelist_corrupted(s, page, &freelist, nextfree))
|
|
break;
|
|
|
|
do {
|
|
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
|
|
index a9e7540c56918..3165f6ff8ee71 100644
|
|
--- a/net/batman-adv/bat_v_ogm.c
|
|
+++ b/net/batman-adv/bat_v_ogm.c
|
|
@@ -878,6 +878,12 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
|
ntohl(ogm_packet->seqno), ogm_throughput, ogm_packet->ttl,
|
|
ogm_packet->version, ntohs(ogm_packet->tvlv_len));
|
|
|
|
+ if (batadv_is_my_mac(bat_priv, ogm_packet->orig)) {
|
|
+ batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
|
+ "Drop packet: originator packet from ourself\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
/* If the throughput metric is 0, immediately drop the packet. No need
|
|
* to create orig_node / neigh_node for an unusable route.
|
|
*/
|
|
@@ -1005,11 +1011,6 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
|
|
if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
|
|
goto free_skb;
|
|
|
|
- ogm_packet = (struct batadv_ogm2_packet *)skb->data;
|
|
-
|
|
- if (batadv_is_my_mac(bat_priv, ogm_packet->orig))
|
|
- goto free_skb;
|
|
-
|
|
batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
|
|
batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
|
|
skb->len + ETH_HLEN);
|
|
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
|
|
index 663a53b6d36e6..5f6309ade1ea1 100644
|
|
--- a/net/batman-adv/bridge_loop_avoidance.c
|
|
+++ b/net/batman-adv/bridge_loop_avoidance.c
|
|
@@ -437,7 +437,10 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
|
|
batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
|
|
skb->len + ETH_HLEN);
|
|
|
|
- netif_rx(skb);
|
|
+ if (in_interrupt())
|
|
+ netif_rx(skb);
|
|
+ else
|
|
+ netif_rx_ni(skb);
|
|
out:
|
|
if (primary_if)
|
|
batadv_hardif_put(primary_if);
|
|
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
|
|
index 47df4c6789886..89c9097007c3a 100644
|
|
--- a/net/batman-adv/gateway_client.c
|
|
+++ b/net/batman-adv/gateway_client.c
|
|
@@ -703,8 +703,10 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
|
|
|
|
chaddr_offset = *header_len + BATADV_DHCP_CHADDR_OFFSET;
|
|
/* store the client address if the message is going to a client */
|
|
- if (ret == BATADV_DHCP_TO_CLIENT &&
|
|
- pskb_may_pull(skb, chaddr_offset + ETH_ALEN)) {
|
|
+ if (ret == BATADV_DHCP_TO_CLIENT) {
|
|
+ if (!pskb_may_pull(skb, chaddr_offset + ETH_ALEN))
|
|
+ return BATADV_DHCP_NO;
|
|
+
|
|
/* check if the DHCP packet carries an Ethernet DHCP */
|
|
p = skb->data + *header_len + BATADV_DHCP_HTYPE_OFFSET;
|
|
if (*p != BATADV_DHCP_HTYPE_ETHERNET)
|
|
diff --git a/net/core/dev.c b/net/core/dev.c
|
|
index 25858f1f67cf7..56cd7b83a3829 100644
|
|
--- a/net/core/dev.c
|
|
+++ b/net/core/dev.c
|
|
@@ -5602,12 +5602,13 @@ static void napi_skb_free_stolen_head(struct sk_buff *skb)
|
|
kmem_cache_free(skbuff_head_cache, skb);
|
|
}
|
|
|
|
-static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
|
|
+static gro_result_t napi_skb_finish(struct napi_struct *napi,
|
|
+ struct sk_buff *skb,
|
|
+ gro_result_t ret)
|
|
{
|
|
switch (ret) {
|
|
case GRO_NORMAL:
|
|
- if (netif_receive_skb_internal(skb))
|
|
- ret = GRO_DROP;
|
|
+ gro_normal_one(napi, skb);
|
|
break;
|
|
|
|
case GRO_DROP:
|
|
@@ -5639,7 +5640,7 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
|
|
|
|
skb_gro_reset_offset(skb);
|
|
|
|
- ret = napi_skb_finish(dev_gro_receive(napi, skb), skb);
|
|
+ ret = napi_skb_finish(napi, skb, dev_gro_receive(napi, skb));
|
|
trace_napi_gro_receive_exit(ret);
|
|
|
|
return ret;
|
|
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
|
|
index f7129232c8250..2023650c27249 100644
|
|
--- a/net/netfilter/nf_tables_api.c
|
|
+++ b/net/netfilter/nf_tables_api.c
|
|
@@ -744,11 +744,11 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,
|
|
nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0,
|
|
family, table);
|
|
if (err < 0)
|
|
- goto err;
|
|
+ goto err_fill_table_info;
|
|
|
|
- return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
|
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
|
|
-err:
|
|
+err_fill_table_info:
|
|
kfree_skb(skb2);
|
|
return err;
|
|
}
|
|
@@ -1443,11 +1443,11 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
|
|
nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0,
|
|
family, table, chain);
|
|
if (err < 0)
|
|
- goto err;
|
|
+ goto err_fill_chain_info;
|
|
|
|
- return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
|
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
|
|
-err:
|
|
+err_fill_chain_info:
|
|
kfree_skb(skb2);
|
|
return err;
|
|
}
|
|
@@ -2622,11 +2622,11 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
|
|
nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
|
|
family, table, chain, rule, NULL);
|
|
if (err < 0)
|
|
- goto err;
|
|
+ goto err_fill_rule_info;
|
|
|
|
- return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
|
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
|
|
-err:
|
|
+err_fill_rule_info:
|
|
kfree_skb(skb2);
|
|
return err;
|
|
}
|
|
@@ -3353,7 +3353,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
|
goto nla_put_failure;
|
|
}
|
|
|
|
- if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
|
|
+ if (set->udata &&
|
|
+ nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
|
|
goto nla_put_failure;
|
|
|
|
desc = nla_nest_start_noflag(skb, NFTA_SET_DESC);
|
|
@@ -3525,11 +3526,11 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
|
|
|
|
err = nf_tables_fill_set(skb2, &ctx, set, NFT_MSG_NEWSET, 0);
|
|
if (err < 0)
|
|
- goto err;
|
|
+ goto err_fill_set_info;
|
|
|
|
- return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
|
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
|
|
-err:
|
|
+err_fill_set_info:
|
|
kfree_skb(skb2);
|
|
return err;
|
|
}
|
|
@@ -4304,24 +4305,18 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
|
err = -ENOMEM;
|
|
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
|
|
if (skb == NULL)
|
|
- goto err1;
|
|
+ return err;
|
|
|
|
err = nf_tables_fill_setelem_info(skb, ctx, ctx->seq, ctx->portid,
|
|
NFT_MSG_NEWSETELEM, 0, set, &elem);
|
|
if (err < 0)
|
|
- goto err2;
|
|
+ goto err_fill_setelem;
|
|
|
|
- err = nfnetlink_unicast(skb, ctx->net, ctx->portid, MSG_DONTWAIT);
|
|
- /* This avoids a loop in nfnetlink. */
|
|
- if (err < 0)
|
|
- goto err1;
|
|
+ return nfnetlink_unicast(skb, ctx->net, ctx->portid);
|
|
|
|
- return 0;
|
|
-err2:
|
|
+err_fill_setelem:
|
|
kfree_skb(skb);
|
|
-err1:
|
|
- /* this avoids a loop in nfnetlink. */
|
|
- return err == -EAGAIN ? -ENOBUFS : err;
|
|
+ return err;
|
|
}
|
|
|
|
/* called with rcu_read_lock held */
|
|
@@ -5498,10 +5493,11 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
|
|
nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
|
|
family, table, obj, reset);
|
|
if (err < 0)
|
|
- goto err;
|
|
+ goto err_fill_obj_info;
|
|
|
|
- return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
|
-err:
|
|
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
+
|
|
+err_fill_obj_info:
|
|
kfree_skb(skb2);
|
|
return err;
|
|
}
|
|
@@ -6173,10 +6169,11 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
|
|
NFT_MSG_NEWFLOWTABLE, 0, family,
|
|
flowtable);
|
|
if (err < 0)
|
|
- goto err;
|
|
+ goto err_fill_flowtable_info;
|
|
|
|
- return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
|
-err:
|
|
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
+
|
|
+err_fill_flowtable_info:
|
|
kfree_skb(skb2);
|
|
return err;
|
|
}
|
|
@@ -6337,10 +6334,11 @@ static int nf_tables_getgen(struct net *net, struct sock *nlsk,
|
|
err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
|
|
nlh->nlmsg_seq);
|
|
if (err < 0)
|
|
- goto err;
|
|
+ goto err_fill_gen_info;
|
|
|
|
- return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
|
-err:
|
|
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
+
|
|
+err_fill_gen_info:
|
|
kfree_skb(skb2);
|
|
return err;
|
|
}
|
|
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
|
|
index 99127e2d95a84..6d03b09096210 100644
|
|
--- a/net/netfilter/nfnetlink.c
|
|
+++ b/net/netfilter/nfnetlink.c
|
|
@@ -148,10 +148,15 @@ int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error)
|
|
}
|
|
EXPORT_SYMBOL_GPL(nfnetlink_set_err);
|
|
|
|
-int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid,
|
|
- int flags)
|
|
+int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid)
|
|
{
|
|
- return netlink_unicast(net->nfnl, skb, portid, flags);
|
|
+ int err;
|
|
+
|
|
+ err = nlmsg_unicast(net->nfnl, skb, portid);
|
|
+ if (err == -EAGAIN)
|
|
+ err = -ENOBUFS;
|
|
+
|
|
+ return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(nfnetlink_unicast);
|
|
|
|
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
|
|
index 0ba020ca38e68..7ca2ca4bba055 100644
|
|
--- a/net/netfilter/nfnetlink_log.c
|
|
+++ b/net/netfilter/nfnetlink_log.c
|
|
@@ -356,8 +356,7 @@ __nfulnl_send(struct nfulnl_instance *inst)
|
|
goto out;
|
|
}
|
|
}
|
|
- nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
|
|
- MSG_DONTWAIT);
|
|
+ nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid);
|
|
out:
|
|
inst->qlen = 0;
|
|
inst->skb = NULL;
|
|
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
|
index feabdfb22920b..6f0a2bad8ad5e 100644
|
|
--- a/net/netfilter/nfnetlink_queue.c
|
|
+++ b/net/netfilter/nfnetlink_queue.c
|
|
@@ -681,7 +681,7 @@ __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue,
|
|
*packet_id_ptr = htonl(entry->id);
|
|
|
|
/* nfnetlink_unicast will either free the nskb or add it to a socket */
|
|
- err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT);
|
|
+ err = nfnetlink_unicast(nskb, net, queue->peer_portid);
|
|
if (err < 0) {
|
|
if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
|
|
failopen = 1;
|
|
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
|
|
index 0e3bfbc26e790..62dc728bf93c9 100644
|
|
--- a/net/netfilter/nft_payload.c
|
|
+++ b/net/netfilter/nft_payload.c
|
|
@@ -79,7 +79,9 @@ void nft_payload_eval(const struct nft_expr *expr,
|
|
u32 *dest = ®s->data[priv->dreg];
|
|
int offset;
|
|
|
|
- dest[priv->len / NFT_REG32_SIZE] = 0;
|
|
+ if (priv->len % NFT_REG32_SIZE)
|
|
+ dest[priv->len / NFT_REG32_SIZE] = 0;
|
|
+
|
|
switch (priv->base) {
|
|
case NFT_PAYLOAD_LL_HEADER:
|
|
if (!skb_mac_header_was_set(skb))
|
|
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
|
|
index 7735340c892eb..fbc2d4dfddf0e 100644
|
|
--- a/net/packet/af_packet.c
|
|
+++ b/net/packet/af_packet.c
|
|
@@ -2169,7 +2169,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
|
|
int skb_len = skb->len;
|
|
unsigned int snaplen, res;
|
|
unsigned long status = TP_STATUS_USER;
|
|
- unsigned short macoff, netoff, hdrlen;
|
|
+ unsigned short macoff, hdrlen;
|
|
+ unsigned int netoff;
|
|
struct sk_buff *copy_skb = NULL;
|
|
struct timespec ts;
|
|
__u32 ts_status;
|
|
@@ -2238,6 +2239,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
|
|
}
|
|
macoff = netoff - maclen;
|
|
}
|
|
+ if (netoff > USHRT_MAX) {
|
|
+ atomic_inc(&po->tp_drops);
|
|
+ goto drop_n_restore;
|
|
+ }
|
|
if (po->tp_version <= TPACKET_V2) {
|
|
if (macoff + snaplen > po->rx_ring.frame_size) {
|
|
if (po->copy_thresh &&
|
|
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
|
|
index 22dec6049e1bb..6cace43b217ee 100644
|
|
--- a/net/rxrpc/input.c
|
|
+++ b/net/rxrpc/input.c
|
|
@@ -844,7 +844,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|
struct rxrpc_ackinfo info;
|
|
u8 acks[RXRPC_MAXACKS];
|
|
} buf;
|
|
- rxrpc_serial_t acked_serial;
|
|
+ rxrpc_serial_t ack_serial, acked_serial;
|
|
rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt;
|
|
int nr_acks, offset, ioffset;
|
|
|
|
@@ -857,6 +857,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|
}
|
|
offset += sizeof(buf.ack);
|
|
|
|
+ ack_serial = sp->hdr.serial;
|
|
acked_serial = ntohl(buf.ack.serial);
|
|
first_soft_ack = ntohl(buf.ack.firstPacket);
|
|
prev_pkt = ntohl(buf.ack.previousPacket);
|
|
@@ -865,31 +866,31 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|
summary.ack_reason = (buf.ack.reason < RXRPC_ACK__INVALID ?
|
|
buf.ack.reason : RXRPC_ACK__INVALID);
|
|
|
|
- trace_rxrpc_rx_ack(call, sp->hdr.serial, acked_serial,
|
|
+ trace_rxrpc_rx_ack(call, ack_serial, acked_serial,
|
|
first_soft_ack, prev_pkt,
|
|
summary.ack_reason, nr_acks);
|
|
|
|
if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
|
|
rxrpc_input_ping_response(call, skb->tstamp, acked_serial,
|
|
- sp->hdr.serial);
|
|
+ ack_serial);
|
|
if (buf.ack.reason == RXRPC_ACK_REQUESTED)
|
|
rxrpc_input_requested_ack(call, skb->tstamp, acked_serial,
|
|
- sp->hdr.serial);
|
|
+ ack_serial);
|
|
|
|
if (buf.ack.reason == RXRPC_ACK_PING) {
|
|
- _proto("Rx ACK %%%u PING Request", sp->hdr.serial);
|
|
+ _proto("Rx ACK %%%u PING Request", ack_serial);
|
|
rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
|
|
- sp->hdr.serial, true, true,
|
|
+ ack_serial, true, true,
|
|
rxrpc_propose_ack_respond_to_ping);
|
|
} else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
|
|
rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED,
|
|
- sp->hdr.serial, true, true,
|
|
+ ack_serial, true, true,
|
|
rxrpc_propose_ack_respond_to_ack);
|
|
}
|
|
|
|
/* Discard any out-of-order or duplicate ACKs (outside lock). */
|
|
if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
|
|
- trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial,
|
|
+ trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
|
|
first_soft_ack, call->ackr_first_seq,
|
|
prev_pkt, call->ackr_prev_seq);
|
|
return;
|
|
@@ -905,7 +906,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|
|
|
/* Discard any out-of-order or duplicate ACKs (inside lock). */
|
|
if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
|
|
- trace_rxrpc_rx_discard_ack(call->debug_id, sp->hdr.serial,
|
|
+ trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
|
|
first_soft_ack, call->ackr_first_seq,
|
|
prev_pkt, call->ackr_prev_seq);
|
|
goto out;
|
|
@@ -965,7 +966,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|
RXRPC_TX_ANNO_LAST &&
|
|
summary.nr_acks == call->tx_top - hard_ack &&
|
|
rxrpc_is_client_call(call))
|
|
- rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
|
|
+ rxrpc_propose_ACK(call, RXRPC_ACK_PING, ack_serial,
|
|
false, true,
|
|
rxrpc_propose_ack_ping_for_lost_reply);
|
|
|
|
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c
|
|
index efce27802a74f..e011594adcd13 100644
|
|
--- a/net/rxrpc/peer_object.c
|
|
+++ b/net/rxrpc/peer_object.c
|
|
@@ -500,11 +500,21 @@ EXPORT_SYMBOL(rxrpc_kernel_get_peer);
|
|
* rxrpc_kernel_get_srtt - Get a call's peer smoothed RTT
|
|
* @sock: The socket on which the call is in progress.
|
|
* @call: The call to query
|
|
+ * @_srtt: Where to store the SRTT value.
|
|
*
|
|
- * Get the call's peer smoothed RTT.
|
|
+ * Get the call's peer smoothed RTT in uS.
|
|
*/
|
|
-u32 rxrpc_kernel_get_srtt(struct socket *sock, struct rxrpc_call *call)
|
|
+bool rxrpc_kernel_get_srtt(struct socket *sock, struct rxrpc_call *call,
|
|
+ u32 *_srtt)
|
|
{
|
|
- return call->peer->srtt_us >> 3;
|
|
+ struct rxrpc_peer *peer = call->peer;
|
|
+
|
|
+ if (peer->rtt_count == 0) {
|
|
+ *_srtt = 1000000; /* 1S */
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ *_srtt = call->peer->srtt_us >> 3;
|
|
+ return true;
|
|
}
|
|
EXPORT_SYMBOL(rxrpc_kernel_get_srtt);
|
|
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
|
|
index 1a8218f1bbe07..20a8e6af88c45 100644
|
|
--- a/net/wireless/reg.c
|
|
+++ b/net/wireless/reg.c
|
|
@@ -2941,6 +2941,9 @@ int regulatory_hint_user(const char *alpha2,
|
|
if (WARN_ON(!alpha2))
|
|
return -EINVAL;
|
|
|
|
+ if (!is_world_regdom(alpha2) && !is_an_alpha2(alpha2))
|
|
+ return -EINVAL;
|
|
+
|
|
request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
|
|
if (!request)
|
|
return -ENOMEM;
|
|
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
|
|
index 6fcc66afb0880..0c9b114202796 100755
|
|
--- a/scripts/checkpatch.pl
|
|
+++ b/scripts/checkpatch.pl
|
|
@@ -2576,8 +2576,8 @@ sub process {
|
|
|
|
# Check if the commit log has what seems like a diff which can confuse patch
|
|
if ($in_commit_log && !$commit_log_has_diff &&
|
|
- (($line =~ m@^\s+diff\b.*a/[\w/]+@ &&
|
|
- $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) ||
|
|
+ (($line =~ m@^\s+diff\b.*a/([\w/]+)@ &&
|
|
+ $line =~ m@^\s+diff\b.*a/[\w/]+\s+b/$1\b@) ||
|
|
$line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ ||
|
|
$line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) {
|
|
ERROR("DIFF_IN_COMMIT_MSG",
|
|
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
|
|
index 3788906421a73..fe27034f28460 100644
|
|
--- a/sound/core/oss/mulaw.c
|
|
+++ b/sound/core/oss/mulaw.c
|
|
@@ -329,8 +329,8 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
|
|
snd_BUG();
|
|
return -EINVAL;
|
|
}
|
|
- if (snd_BUG_ON(!snd_pcm_format_linear(format->format)))
|
|
- return -ENXIO;
|
|
+ if (!snd_pcm_format_linear(format->format))
|
|
+ return -EINVAL;
|
|
|
|
err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion",
|
|
src_format, dst_format,
|
|
diff --git a/sound/firewire/digi00x/digi00x.c b/sound/firewire/digi00x/digi00x.c
|
|
index 1f5fc0e7c0243..0e4b0eac30159 100644
|
|
--- a/sound/firewire/digi00x/digi00x.c
|
|
+++ b/sound/firewire/digi00x/digi00x.c
|
|
@@ -14,6 +14,7 @@ MODULE_LICENSE("GPL v2");
|
|
#define VENDOR_DIGIDESIGN 0x00a07e
|
|
#define MODEL_CONSOLE 0x000001
|
|
#define MODEL_RACK 0x000002
|
|
+#define SPEC_VERSION 0x000001
|
|
|
|
static int name_card(struct snd_dg00x *dg00x)
|
|
{
|
|
@@ -175,14 +176,18 @@ static const struct ieee1394_device_id snd_dg00x_id_table[] = {
|
|
/* Both of 002/003 use the same ID. */
|
|
{
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
+ IEEE1394_MATCH_VERSION |
|
|
IEEE1394_MATCH_MODEL_ID,
|
|
.vendor_id = VENDOR_DIGIDESIGN,
|
|
+ .version = SPEC_VERSION,
|
|
.model_id = MODEL_CONSOLE,
|
|
},
|
|
{
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
+ IEEE1394_MATCH_VERSION |
|
|
IEEE1394_MATCH_MODEL_ID,
|
|
.vendor_id = VENDOR_DIGIDESIGN,
|
|
+ .version = SPEC_VERSION,
|
|
.model_id = MODEL_RACK,
|
|
},
|
|
{}
|
|
diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c
|
|
index addc464503bcf..0175e3e835ead 100644
|
|
--- a/sound/firewire/tascam/tascam.c
|
|
+++ b/sound/firewire/tascam/tascam.c
|
|
@@ -39,9 +39,6 @@ static const struct snd_tscm_spec model_specs[] = {
|
|
.midi_capture_ports = 2,
|
|
.midi_playback_ports = 4,
|
|
},
|
|
- // This kernel module doesn't support FE-8 because the most of features
|
|
- // can be implemented in userspace without any specific support of this
|
|
- // module.
|
|
};
|
|
|
|
static int identify_model(struct snd_tscm *tscm)
|
|
@@ -211,11 +208,39 @@ static void snd_tscm_remove(struct fw_unit *unit)
|
|
}
|
|
|
|
static const struct ieee1394_device_id snd_tscm_id_table[] = {
|
|
+ // Tascam, FW-1884.
|
|
+ {
|
|
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
+ IEEE1394_MATCH_SPECIFIER_ID |
|
|
+ IEEE1394_MATCH_VERSION,
|
|
+ .vendor_id = 0x00022e,
|
|
+ .specifier_id = 0x00022e,
|
|
+ .version = 0x800000,
|
|
+ },
|
|
+ // Tascam, FE-8 (.version = 0x800001)
|
|
+ // This kernel module doesn't support FE-8 because the most of features
|
|
+ // can be implemented in userspace without any specific support of this
|
|
+ // module.
|
|
+ //
|
|
+ // .version = 0x800002 is unknown.
|
|
+ //
|
|
+ // Tascam, FW-1082.
|
|
+ {
|
|
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
+ IEEE1394_MATCH_SPECIFIER_ID |
|
|
+ IEEE1394_MATCH_VERSION,
|
|
+ .vendor_id = 0x00022e,
|
|
+ .specifier_id = 0x00022e,
|
|
+ .version = 0x800003,
|
|
+ },
|
|
+ // Tascam, FW-1804.
|
|
{
|
|
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
|
- IEEE1394_MATCH_SPECIFIER_ID,
|
|
+ IEEE1394_MATCH_SPECIFIER_ID |
|
|
+ IEEE1394_MATCH_VERSION,
|
|
.vendor_id = 0x00022e,
|
|
.specifier_id = 0x00022e,
|
|
+ .version = 0x800004,
|
|
},
|
|
{}
|
|
};
|
|
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
|
|
index 478412e0aa3c7..7aedaeb7a1968 100644
|
|
--- a/sound/pci/ca0106/ca0106_main.c
|
|
+++ b/sound/pci/ca0106/ca0106_main.c
|
|
@@ -537,7 +537,8 @@ static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id,
|
|
else
|
|
/* Power down */
|
|
chip->spi_dac_reg[reg] |= bit;
|
|
- return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
|
|
+ if (snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]) != 0)
|
|
+ return -ENXIO;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
|
|
index 3a456410937b5..7353d2ec359ae 100644
|
|
--- a/sound/pci/hda/hda_intel.c
|
|
+++ b/sound/pci/hda/hda_intel.c
|
|
@@ -2671,8 +2671,6 @@ static const struct pci_device_id azx_ids[] = {
|
|
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
|
|
/* Zhaoxin */
|
|
{ PCI_DEVICE(0x1d17, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN },
|
|
- /* Loongson */
|
|
- { PCI_DEVICE(0x0014, 0x7a07), .driver_data = AZX_DRIVER_GENERIC },
|
|
{ 0, }
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, azx_ids);
|
|
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
|
|
index ec9460f3a288e..a13bad262598d 100644
|
|
--- a/sound/pci/hda/patch_hdmi.c
|
|
+++ b/sound/pci/hda/patch_hdmi.c
|
|
@@ -2798,6 +2798,7 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec,
|
|
hda_nid_t cvt_nid)
|
|
{
|
|
if (per_pin) {
|
|
+ haswell_verify_D0(codec, per_pin->cvt_nid, per_pin->pin_nid);
|
|
snd_hda_set_dev_select(codec, per_pin->pin_nid,
|
|
per_pin->dev_id);
|
|
intel_verify_pin_cvt_connect(codec, per_pin);
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index d1b74c7cacd76..d614090dae49d 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -2466,6 +2466,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
|
|
SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
|
|
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
|
|
+ SND_PCI_QUIRK(0x1462, 0x9c37, "MSI X570-A PRO", ALC1220_FIXUP_CLEVO_P950),
|
|
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
|
|
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
|
|
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
|
|
@@ -5849,6 +5850,39 @@ static void alc275_fixup_gpio4_off(struct hda_codec *codec,
|
|
}
|
|
}
|
|
|
|
+/* Quirk for Thinkpad X1 7th and 8th Gen
|
|
+ * The following fixed routing needed
|
|
+ * DAC1 (NID 0x02) -> Speaker (NID 0x14); some eq applied secretly
|
|
+ * DAC2 (NID 0x03) -> Bass (NID 0x17) & Headphone (NID 0x21); sharing a DAC
|
|
+ * DAC3 (NID 0x06) -> Unused, due to the lack of volume amp
|
|
+ */
|
|
+static void alc285_fixup_thinkpad_x1_gen7(struct hda_codec *codec,
|
|
+ const struct hda_fixup *fix, int action)
|
|
+{
|
|
+ static const hda_nid_t conn[] = { 0x02, 0x03 }; /* exclude 0x06 */
|
|
+ static const hda_nid_t preferred_pairs[] = {
|
|
+ 0x14, 0x02, 0x17, 0x03, 0x21, 0x03, 0
|
|
+ };
|
|
+ struct alc_spec *spec = codec->spec;
|
|
+
|
|
+ switch (action) {
|
|
+ case HDA_FIXUP_ACT_PRE_PROBE:
|
|
+ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
|
|
+ spec->gen.preferred_dacs = preferred_pairs;
|
|
+ break;
|
|
+ case HDA_FIXUP_ACT_BUILD:
|
|
+ /* The generic parser creates somewhat unintuitive volume ctls
|
|
+ * with the fixed routing above, and the shared DAC2 may be
|
|
+ * confusing for PA.
|
|
+ * Rename those to unique names so that PA doesn't touch them
|
|
+ * and use only Master volume.
|
|
+ */
|
|
+ rename_ctl(codec, "Front Playback Volume", "DAC1 Playback Volume");
|
|
+ rename_ctl(codec, "Bass Speaker Playback Volume", "DAC2 Playback Volume");
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
static void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec,
|
|
const struct hda_fixup *fix,
|
|
int action)
|
|
@@ -6117,6 +6151,7 @@ enum {
|
|
ALC289_FIXUP_DUAL_SPK,
|
|
ALC294_FIXUP_SPK2_TO_DAC1,
|
|
ALC294_FIXUP_ASUS_DUAL_SPK,
|
|
+ ALC285_FIXUP_THINKPAD_X1_GEN7,
|
|
ALC285_FIXUP_THINKPAD_HEADSET_JACK,
|
|
ALC294_FIXUP_ASUS_HPE,
|
|
ALC294_FIXUP_ASUS_COEF_1B,
|
|
@@ -7262,11 +7297,17 @@ static const struct hda_fixup alc269_fixups[] = {
|
|
.chained = true,
|
|
.chain_id = ALC294_FIXUP_SPK2_TO_DAC1
|
|
},
|
|
+ [ALC285_FIXUP_THINKPAD_X1_GEN7] = {
|
|
+ .type = HDA_FIXUP_FUNC,
|
|
+ .v.func = alc285_fixup_thinkpad_x1_gen7,
|
|
+ .chained = true,
|
|
+ .chain_id = ALC269_FIXUP_THINKPAD_ACPI
|
|
+ },
|
|
[ALC285_FIXUP_THINKPAD_HEADSET_JACK] = {
|
|
.type = HDA_FIXUP_FUNC,
|
|
.v.func = alc_fixup_headset_jack,
|
|
.chained = true,
|
|
- .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1
|
|
+ .chain_id = ALC285_FIXUP_THINKPAD_X1_GEN7
|
|
},
|
|
[ALC294_FIXUP_ASUS_HPE] = {
|
|
.type = HDA_FIXUP_VERBS,
|
|
@@ -7677,7 +7718,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
|
SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
|
SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
|
- SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
|
+ SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
|
+ SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
|
SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
|
|
SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
|
|
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
|
|
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
|
|
index 7b41f97489788..878f1201aad6e 100644
|
|
--- a/sound/usb/pcm.c
|
|
+++ b/sound/usb/pcm.c
|
|
@@ -356,6 +356,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
|
|
case USB_ID(0x07fd, 0x0008): /* MOTU M Series */
|
|
case USB_ID(0x31e9, 0x0001): /* Solid State Logic SSL2 */
|
|
case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */
|
|
+ case USB_ID(0x0499, 0x172f): /* Steinberg UR22C */
|
|
case USB_ID(0x0d9a, 0x00df): /* RTX6001 */
|
|
ep = 0x81;
|
|
ifnum = 2;
|
|
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
|
|
index bb7b271397a66..fabe5aeaa351a 100644
|
|
--- a/tools/include/uapi/linux/perf_event.h
|
|
+++ b/tools/include/uapi/linux/perf_event.h
|
|
@@ -1131,7 +1131,7 @@ union perf_mem_data_src {
|
|
|
|
#define PERF_MEM_SNOOPX_FWD 0x01 /* forward */
|
|
/* 1 free */
|
|
-#define PERF_MEM_SNOOPX_SHIFT 37
|
|
+#define PERF_MEM_SNOOPX_SHIFT 38
|
|
|
|
/* locked instruction */
|
|
#define PERF_MEM_LOCK_NA 0x01 /* not available */
|
|
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
|
|
index 23332861de6e4..454e275cd5dff 100644
|
|
--- a/tools/perf/builtin-record.c
|
|
+++ b/tools/perf/builtin-record.c
|
|
@@ -2137,7 +2137,7 @@ static struct option __record_options[] = {
|
|
OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
|
|
"synthesize non-sample events at the end of output"),
|
|
OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
|
|
- OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"),
|
|
+ OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "do not record bpf events"),
|
|
OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
|
|
"Fail if the specified frequency can't be used"),
|
|
OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
|
|
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
|
|
index 99e3fd04a5cb3..d36ae65ae3330 100644
|
|
--- a/tools/perf/pmu-events/jevents.c
|
|
+++ b/tools/perf/pmu-events/jevents.c
|
|
@@ -137,7 +137,7 @@ static char *fixregex(char *s)
|
|
return s;
|
|
|
|
/* allocate space for a new string */
|
|
- fixed = (char *) malloc(len + 1);
|
|
+ fixed = (char *) malloc(len + esc_count + 1);
|
|
if (!fixed)
|
|
return NULL;
|
|
|
|
diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
|
|
index c812f0178b643..1c4219ceced2f 100644
|
|
--- a/tools/testing/selftests/bpf/test_maps.c
|
|
+++ b/tools/testing/selftests/bpf/test_maps.c
|
|
@@ -1282,6 +1282,8 @@ static void __run_parallel(unsigned int tasks,
|
|
pid_t pid[tasks];
|
|
int i;
|
|
|
|
+ fflush(stdout);
|
|
+
|
|
for (i = 0; i < tasks; i++) {
|
|
pid[i] = fork();
|
|
if (pid[i] == 0) {
|