1
0
Fork 0

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

hifive-unleashed-5.1
David S. Miller 2018-04-24 23:59:11 -04:00
commit c749fa181b
221 changed files with 2738 additions and 1484 deletions

View File

@ -1373,7 +1373,8 @@ F: arch/arm/mach-ebsa110/
F: drivers/net/ethernet/amd/am79c961a.*
ARM/ENERGY MICRO (SILICON LABS) EFM32 SUPPORT
M: Uwe Kleine-König <kernel@pengutronix.de>
M: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
N: efm32
@ -1401,7 +1402,8 @@ F: arch/arm/mach-footbridge/
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
M: Shawn Guo <shawnguo@kernel.org>
M: Sascha Hauer <kernel@pengutronix.de>
M: Sascha Hauer <s.hauer@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
R: Fabio Estevam <fabio.estevam@nxp.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -1416,7 +1418,8 @@ F: include/soc/imx/
ARM/FREESCALE VYBRID ARM ARCHITECTURE
M: Shawn Guo <shawnguo@kernel.org>
M: Sascha Hauer <kernel@pengutronix.de>
M: Sascha Hauer <s.hauer@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
R: Stefan Agner <stefan@agner.ch>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -4245,6 +4248,9 @@ F: include/trace/events/fs_dax.h
DEVICE DIRECT ACCESS (DAX)
M: Dan Williams <dan.j.williams@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Vishal Verma <vishal.l.verma@intel.com>
L: linux-nvdimm@lists.01.org
S: Supported
F: drivers/dax/
@ -5651,7 +5657,8 @@ F: drivers/net/ethernet/freescale/fec.h
F: Documentation/devicetree/bindings/net/fsl-fec.txt
FREESCALE IMX / MXC FRAMEBUFFER DRIVER
M: Sascha Hauer <kernel@pengutronix.de>
M: Sascha Hauer <s.hauer@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
L: linux-fbdev@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -6263,7 +6270,7 @@ S: Odd Fixes
F: drivers/media/usb/hdpvr/
HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER
M: Jimmy Vance <jimmy.vance@hpe.com>
M: Jerry Hoemann <jerry.hoemann@hpe.com>
S: Supported
F: Documentation/watchdog/hpwdt.txt
F: drivers/watchdog/hpwdt.c
@ -8055,6 +8062,9 @@ F: tools/lib/lockdep/
LIBNVDIMM BLK: MMIO-APERTURE DRIVER
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Dan Williams <dan.j.williams@intel.com>
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
L: linux-nvdimm@lists.01.org
Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
S: Supported
@ -8063,6 +8073,9 @@ F: drivers/nvdimm/region_devs.c
LIBNVDIMM BTT: BLOCK TRANSLATION TABLE
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dan Williams <dan.j.williams@intel.com>
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Dave Jiang <dave.jiang@intel.com>
L: linux-nvdimm@lists.01.org
Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
S: Supported
@ -8070,6 +8083,9 @@ F: drivers/nvdimm/btt*
LIBNVDIMM PMEM: PERSISTENT MEMORY DRIVER
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Dan Williams <dan.j.williams@intel.com>
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
L: linux-nvdimm@lists.01.org
Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
S: Supported
@ -8085,6 +8101,9 @@ F: Documentation/devicetree/bindings/pmem/pmem-region.txt
LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM
M: Dan Williams <dan.j.williams@intel.com>
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
L: linux-nvdimm@lists.01.org
Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git
@ -12824,7 +12843,8 @@ F: include/linux/siphash.h
SIOX
M: Gavin Schenk <g.schenk@eckelmann.de>
M: Uwe Kleine-König <kernel@pengutronix.de>
M: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
S: Supported
F: drivers/siox/*
F: include/trace/events/siox.h

View File

@ -2,7 +2,7 @@
VERSION = 4
PATCHLEVEL = 17
SUBLEVEL = 0
EXTRAVERSION = -rc1
EXTRAVERSION = -rc2
NAME = Fearless Coyote
# *DOCUMENTATION*

View File

@ -366,7 +366,7 @@ void force_signal_inject(int signal, int code, unsigned long address)
}
/* Force signals we don't understand to SIGKILL */
if (WARN_ON(signal != SIGKILL ||
if (WARN_ON(signal != SIGKILL &&
siginfo_layout(signal, code) != SIL_FAULT)) {
signal = SIGKILL;
}

View File

@ -204,7 +204,7 @@ void __init kasan_init(void)
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
pfn_to_nid(virt_to_pfn(lm_alias(_text))));
early_pfn_to_nid(virt_to_pfn(lm_alias(_text))));
kasan_populate_zero_shadow((void *)KASAN_SHADOW_START,
(void *)mod_shadow_start);
@ -224,7 +224,7 @@ void __init kasan_init(void)
kasan_map_populate((unsigned long)kasan_mem_to_shadow(start),
(unsigned long)kasan_mem_to_shadow(end),
pfn_to_nid(virt_to_pfn(start)));
early_pfn_to_nid(virt_to_pfn(start)));
}
/*

View File

@ -1093,7 +1093,7 @@ static int show_spu_loadavg(struct seq_file *s, void *private)
LOAD_INT(c), LOAD_FRAC(c),
count_active_contexts(),
atomic_read(&nr_spu_contexts),
idr_get_cursor(&task_active_pid_ns(current)->idr));
idr_get_cursor(&task_active_pid_ns(current)->idr) - 1);
return 0;
}

View File

@ -3028,10 +3028,27 @@ static struct intel_uncore_type bdx_uncore_cbox = {
.format_group = &hswep_uncore_cbox_format_group,
};
static struct intel_uncore_type bdx_uncore_sbox = {
.name = "sbox",
.num_counters = 4,
.num_boxes = 4,
.perf_ctr_bits = 48,
.event_ctl = HSWEP_S0_MSR_PMON_CTL0,
.perf_ctr = HSWEP_S0_MSR_PMON_CTR0,
.event_mask = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
.box_ctl = HSWEP_S0_MSR_PMON_BOX_CTL,
.msr_offset = HSWEP_SBOX_MSR_OFFSET,
.ops = &hswep_uncore_sbox_msr_ops,
.format_group = &hswep_uncore_sbox_format_group,
};
#define BDX_MSR_UNCORE_SBOX 3
static struct intel_uncore_type *bdx_msr_uncores[] = {
&bdx_uncore_ubox,
&bdx_uncore_cbox,
&hswep_uncore_pcu,
&bdx_uncore_sbox,
NULL,
};
@ -3043,10 +3060,25 @@ static struct event_constraint bdx_uncore_pcu_constraints[] = {
void bdx_uncore_cpu_init(void)
{
int pkg = topology_phys_to_logical_pkg(0);
if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
uncore_msr_uncores = bdx_msr_uncores;
/* BDX-DE doesn't have SBOX */
if (boot_cpu_data.x86_model == 86) {
uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
/* Detect systems with no SBOXes */
} else if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) {
struct pci_dev *pdev;
u32 capid4;
pdev = uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3];
pci_read_config_dword(pdev, 0x94, &capid4);
if (((capid4 >> 6) & 0x3) == 0)
bdx_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
}
hswep_uncore_pcu.constraints = bdx_uncore_pcu_constraints;
}
@ -3264,6 +3296,11 @@ static const struct pci_device_id bdx_uncore_pci_ids[] = {
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f46),
.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 2),
},
{ /* PCU.3 (for Capability registers) */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fc0),
.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
HSWEP_PCI_PCU_3),
},
{ /* end: all zeroes */ }
};

View File

@ -136,7 +136,6 @@
#endif
#ifndef __ASSEMBLY__
#ifndef __BPF__
/*
* This output constraint should be used for any inline asm which has a "call"
* instruction. Otherwise the asm may be inserted before the frame pointer
@ -146,6 +145,5 @@
register unsigned long current_stack_pointer asm(_ASM_SP);
#define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer)
#endif
#endif
#endif /* _ASM_X86_ASM_H */

View File

@ -749,13 +749,11 @@ enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
extern void enable_sep_cpu(void);
extern int sysenter_setup(void);
extern void early_trap_init(void);
void early_trap_pf_init(void);
/* Defined in head.S */
extern struct desc_ptr early_gdt_descr;
extern void cpu_set_gdt(int);
extern void switch_to_new_gdt(int);
extern void load_direct_gdt(int);
extern void load_fixmap_gdt(int);

View File

@ -215,6 +215,10 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
apic_id = processor->local_apic_id;
enabled = processor->lapic_flags & ACPI_MADT_ENABLED;
/* Ignore invalid ID */
if (apic_id == 0xffffffff)
return 0;
/*
* We need to register disabled CPU as well to permit
* counting disabled CPUs. This allows us to size

View File

@ -398,11 +398,10 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
* little bit simple
*/
efi_map_sz = efi_get_runtime_map_size();
efi_map_sz = ALIGN(efi_map_sz, 16);
params_cmdline_sz = sizeof(struct boot_params) + cmdline_len +
MAX_ELFCOREHDR_STR_LEN;
params_cmdline_sz = ALIGN(params_cmdline_sz, 16);
kbuf.bufsz = params_cmdline_sz + efi_map_sz +
kbuf.bufsz = params_cmdline_sz + ALIGN(efi_map_sz, 16) +
sizeof(struct setup_data) +
sizeof(struct efi_setup_data);
@ -410,7 +409,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
if (!params)
return ERR_PTR(-ENOMEM);
efi_map_offset = params_cmdline_sz;
efi_setup_data_offset = efi_map_offset + efi_map_sz;
efi_setup_data_offset = efi_map_offset + ALIGN(efi_map_sz, 16);
/* Copy setup header onto bootparams. Documentation/x86/boot.txt */
setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset;

View File

@ -1,90 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/* Fallback functions when the main IOMMU code is not compiled in. This
code is roughly equivalent to i386. */
#include <linux/dma-direct.h>
#include <linux/scatterlist.h>
#include <linux/string.h>
#include <linux/gfp.h>
#include <linux/pci.h>
#include <linux/mm.h>
#include <asm/processor.h>
#include <asm/iommu.h>
#include <asm/dma.h>
#define NOMMU_MAPPING_ERROR 0
static int
check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
{
if (hwdev && !dma_capable(hwdev, bus, size)) {
if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
printk(KERN_ERR
"nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
name, (long long)bus, size,
(long long)*hwdev->dma_mask);
return 0;
}
return 1;
}
static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset;
WARN_ON(size == 0);
if (!check_addr("map_single", dev, bus, size))
return NOMMU_MAPPING_ERROR;
return bus;
}
/* Map a set of buffers described by scatterlist in streaming
* mode for DMA. This is the scatter-gather version of the
* above pci_map_single interface. Here the scatter gather list
* elements are each tagged with the appropriate dma address
* and length. They are obtained via sg_dma_{address,length}(SG).
*
* NOTE: An implementation may be able to use a smaller number of
* DMA address/length pairs than there are SG table elements.
* (for example via virtual mapping capabilities)
* The routine returns the number of addr/length pairs actually
* used, at most nents.
*
* Device ownership issues as mentioned above for pci_map_single are
* the same here.
*/
static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
unsigned long attrs)
{
struct scatterlist *s;
int i;
WARN_ON(nents == 0 || sg[0].length == 0);
for_each_sg(sg, s, nents, i) {
BUG_ON(!sg_page(s));
s->dma_address = sg_phys(s);
if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
return 0;
s->dma_length = s->length;
}
return nents;
}
static int nommu_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
return dma_addr == NOMMU_MAPPING_ERROR;
}
const struct dma_map_ops nommu_dma_ops = {
.alloc = dma_generic_alloc_coherent,
.free = dma_generic_free_coherent,
.map_sg = nommu_map_sg,
.map_page = nommu_map_page,
.is_phys = 1,
.mapping_error = nommu_mapping_error,
.dma_supported = x86_dma_supported,
};

View File

@ -77,6 +77,8 @@
#include <asm/i8259.h>
#include <asm/misc.h>
#include <asm/qspinlock.h>
#include <asm/intel-family.h>
#include <asm/cpu_device_id.h>
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
@ -390,15 +392,47 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
return false;
}
/*
* Define snc_cpu[] for SNC (Sub-NUMA Cluster) CPUs.
*
* These are Intel CPUs that enumerate an LLC that is shared by
* multiple NUMA nodes. The LLC on these systems is shared for
* off-package data access but private to the NUMA node (half
* of the package) for on-package access.
*
* CPUID (the source of the information about the LLC) can only
* enumerate the cache as being shared *or* unshared, but not
* this particular configuration. The CPU in this case enumerates
* the cache to be shared across the entire package (spanning both
* NUMA nodes).
*/
static const struct x86_cpu_id snc_cpu[] = {
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_SKYLAKE_X },
{}
};
static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
{
int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
if (per_cpu(cpu_llc_id, cpu1) != BAD_APICID &&
per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2))
return topology_sane(c, o, "llc");
/* Do not match if we do not have a valid APICID for cpu: */
if (per_cpu(cpu_llc_id, cpu1) == BAD_APICID)
return false;
return false;
/* Do not match if LLC id does not match: */
if (per_cpu(cpu_llc_id, cpu1) != per_cpu(cpu_llc_id, cpu2))
return false;
/*
* Allow the SNC topology without warning. Return of false
* means 'c' does not share the LLC of 'o'. This will be
* reflected to userspace.
*/
if (!topology_same_node(c, o) && x86_match_cpu(snc_cpu))
return false;
return topology_sane(c, o, "llc");
}
/*
@ -456,7 +490,8 @@ static struct sched_domain_topology_level x86_topology[] = {
/*
* Set if a package/die has multiple NUMA nodes inside.
* AMD Magny-Cours and Intel Cluster-on-Die have this.
* AMD Magny-Cours, Intel Cluster-on-Die, and Intel
* Sub-NUMA Clustering have this.
*/
static bool x86_has_numa_in_package;

View File

@ -317,7 +317,7 @@ static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2)
hpet2 -= hpet1;
tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
do_div(tmp, 1000000);
do_div(deltatsc, tmp);
deltatsc = div64_u64(deltatsc, tmp);
return (unsigned long) deltatsc;
}

View File

@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/highmem.h>
#include <asm/pgtable.h>
@ -334,16 +335,16 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
pgprotval_t eff_in, unsigned long P)
{
int i;
pte_t *start;
pte_t *pte;
pgprotval_t prot, eff;
start = (pte_t *)pmd_page_vaddr(addr);
for (i = 0; i < PTRS_PER_PTE; i++) {
prot = pte_flags(*start);
eff = effective_prot(eff_in, prot);
st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
pte = pte_offset_map(&addr, st->current_address);
prot = pte_flags(*pte);
eff = effective_prot(eff_in, prot);
note_page(m, st, __pgprot(prot), eff, 5);
start++;
pte_unmap(pte);
}
}
#ifdef CONFIG_KASAN

View File

@ -98,7 +98,7 @@ static int set_up_temporary_text_mapping(pgd_t *pgd)
set_pgd(pgd + pgd_index(restore_jump_address), new_pgd);
} else {
/* No p4d for 4-level paging: point the pgd to the pud page table */
pgd_t new_pgd = __pgd(__pa(p4d) | pgprot_val(pgtable_prot));
pgd_t new_pgd = __pgd(__pa(pud) | pgprot_val(pgtable_prot));
set_pgd(pgd + pgd_index(restore_jump_address), new_pgd);
}

View File

@ -427,8 +427,9 @@ struct crng_state primary_crng = {
* its value (from 0->1->2).
*/
static int crng_init = 0;
#define crng_ready() (likely(crng_init > 0))
#define crng_ready() (likely(crng_init > 1))
static int crng_init_cnt = 0;
static unsigned long crng_global_init_time = 0;
#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
static void _extract_crng(struct crng_state *crng,
__u32 out[CHACHA20_BLOCK_WORDS]);
@ -787,6 +788,36 @@ static void crng_initialize(struct crng_state *crng)
crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
}
#ifdef CONFIG_NUMA
static void numa_crng_init(void)
{
int i;
struct crng_state *crng;
struct crng_state **pool;
pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
for_each_online_node(i) {
crng = kmalloc_node(sizeof(struct crng_state),
GFP_KERNEL | __GFP_NOFAIL, i);
spin_lock_init(&crng->lock);
crng_initialize(crng);
pool[i] = crng;
}
mb();
if (cmpxchg(&crng_node_pool, NULL, pool)) {
for_each_node(i)
kfree(pool[i]);
kfree(pool);
}
}
#else
static void numa_crng_init(void) {}
#endif
/*
* crng_fast_load() can be called by code in the interrupt service
* path. So we can't afford to dilly-dally.
*/
static int crng_fast_load(const char *cp, size_t len)
{
unsigned long flags;
@ -794,7 +825,7 @@ static int crng_fast_load(const char *cp, size_t len)
if (!spin_trylock_irqsave(&primary_crng.lock, flags))
return 0;
if (crng_ready()) {
if (crng_init != 0) {
spin_unlock_irqrestore(&primary_crng.lock, flags);
return 0;
}
@ -813,6 +844,51 @@ static int crng_fast_load(const char *cp, size_t len)
return 1;
}
/*
* crng_slow_load() is called by add_device_randomness, which has two
* attributes. (1) We can't trust the buffer passed to it is
* guaranteed to be unpredictable (so it might not have any entropy at
* all), and (2) it doesn't have the performance constraints of
* crng_fast_load().
*
* So we do something more comprehensive which is guaranteed to touch
* all of the primary_crng's state, and which uses a LFSR with a
* period of 255 as part of the mixing algorithm. Finally, we do
* *not* advance crng_init_cnt since buffer we may get may be something
* like a fixed DMI table (for example), which might very well be
* unique to the machine, but is otherwise unvarying.
*/
static int crng_slow_load(const char *cp, size_t len)
{
unsigned long flags;
static unsigned char lfsr = 1;
unsigned char tmp;
unsigned i, max = CHACHA20_KEY_SIZE;
const char * src_buf = cp;
char * dest_buf = (char *) &primary_crng.state[4];
if (!spin_trylock_irqsave(&primary_crng.lock, flags))
return 0;
if (crng_init != 0) {
spin_unlock_irqrestore(&primary_crng.lock, flags);
return 0;
}
if (len > max)
max = len;
for (i = 0; i < max ; i++) {
tmp = lfsr;
lfsr >>= 1;
if (tmp & 1)
lfsr ^= 0xE1;
tmp = dest_buf[i % CHACHA20_KEY_SIZE];
dest_buf[i % CHACHA20_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
lfsr += (tmp << 3) | (tmp >> 5);
}
spin_unlock_irqrestore(&primary_crng.lock, flags);
return 1;
}
static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
{
unsigned long flags;
@ -831,7 +907,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
_crng_backtrack_protect(&primary_crng, buf.block,
CHACHA20_KEY_SIZE);
}
spin_lock_irqsave(&primary_crng.lock, flags);
spin_lock_irqsave(&crng->lock, flags);
for (i = 0; i < 8; i++) {
unsigned long rv;
if (!arch_get_random_seed_long(&rv) &&
@ -841,9 +917,10 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
}
memzero_explicit(&buf, sizeof(buf));
crng->init_time = jiffies;
spin_unlock_irqrestore(&primary_crng.lock, flags);
spin_unlock_irqrestore(&crng->lock, flags);
if (crng == &primary_crng && crng_init < 2) {
invalidate_batched_entropy();
numa_crng_init();
crng_init = 2;
process_random_ready_list();
wake_up_interruptible(&crng_init_wait);
@ -856,8 +933,9 @@ static void _extract_crng(struct crng_state *crng,
{
unsigned long v, flags;
if (crng_init > 1 &&
time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
if (crng_ready() &&
(time_after(crng_global_init_time, crng->init_time) ||
time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)))
crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
spin_lock_irqsave(&crng->lock, flags);
if (arch_get_random_long(&v))
@ -981,10 +1059,8 @@ void add_device_randomness(const void *buf, unsigned int size)
unsigned long time = random_get_entropy() ^ jiffies;
unsigned long flags;
if (!crng_ready()) {
crng_fast_load(buf, size);
return;
}
if (!crng_ready() && size)
crng_slow_load(buf, size);
trace_add_device_randomness(size, _RET_IP_);
spin_lock_irqsave(&input_pool.lock, flags);
@ -1139,7 +1215,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
fast_mix(fast_pool);
add_interrupt_bench(cycles);
if (!crng_ready()) {
if (unlikely(crng_init == 0)) {
if ((fast_pool->count >= 64) &&
crng_fast_load((char *) fast_pool->pool,
sizeof(fast_pool->pool))) {
@ -1680,28 +1756,10 @@ static void init_std_data(struct entropy_store *r)
*/
static int rand_initialize(void)
{
#ifdef CONFIG_NUMA
int i;
struct crng_state *crng;
struct crng_state **pool;
#endif
init_std_data(&input_pool);
init_std_data(&blocking_pool);
crng_initialize(&primary_crng);
#ifdef CONFIG_NUMA
pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
for_each_online_node(i) {
crng = kmalloc_node(sizeof(struct crng_state),
GFP_KERNEL | __GFP_NOFAIL, i);
spin_lock_init(&crng->lock);
crng_initialize(crng);
pool[i] = crng;
}
mb();
crng_node_pool = pool;
#endif
crng_global_init_time = jiffies;
return 0;
}
early_initcall(rand_initialize);
@ -1875,6 +1933,14 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
input_pool.entropy_count = 0;
blocking_pool.entropy_count = 0;
return 0;
case RNDRESEEDCRNG:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (crng_init < 2)
return -ENODATA;
crng_reseed(&primary_crng, NULL);
crng_global_init_time = jiffies - 1;
return 0;
default:
return -EINVAL;
}
@ -2212,7 +2278,7 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
{
struct entropy_store *poolp = &input_pool;
if (!crng_ready()) {
if (unlikely(crng_init == 0)) {
crng_fast_load(buffer, count);
return;
}

View File

@ -114,7 +114,7 @@ static int tpm_set_next_event(unsigned long delta,
* of writing CNT registers which may cause the min_delta event got
* missed, so we need add a ETIME check here in case it happened.
*/
return (int)((next - now) <= 0) ? -ETIME : 0;
return (int)(next - now) <= 0 ? -ETIME : 0;
}
static int tpm_set_state_oneshot(struct clock_event_device *evt)

View File

@ -19,6 +19,7 @@
#include <linux/dax.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include "dax-private.h"
#include "dax.h"
@ -540,6 +541,7 @@ static const struct file_operations dax_fops = {
.release = dax_release,
.get_unmapped_area = dax_get_unmapped_area,
.mmap = dax_mmap,
.mmap_supported_flags = MAP_SYNC,
};
static void dev_dax_release(struct device *dev)

View File

@ -138,13 +138,6 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc)
lut = (struct drm_color_lut *)blob->data;
lut_size = blob->length / sizeof(struct drm_color_lut);
if (__is_lut_linear(lut, lut_size)) {
/* Set to bypass if lut is set to linear */
stream->out_transfer_func->type = TF_TYPE_BYPASS;
stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
return 0;
}
gamma = dc_create_gamma();
if (!gamma)
return -ENOMEM;

View File

@ -4743,23 +4743,27 @@ static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
for (i=0; i < dep_table->count; i++) {
if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
break;
data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK;
return;
}
}
if (i == dep_table->count)
if (i == dep_table->count && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC;
data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
}
dep_table = table_info->vdd_dep_on_sclk;
odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk);
for (i=0; i < dep_table->count; i++) {
if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
break;
data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK;
return;
}
}
if (i == dep_table->count)
if (i == dep_table->count && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC;
data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
}
}
static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,

View File

@ -412,8 +412,10 @@ typedef struct {
QuadraticInt_t ReservedEquation2;
QuadraticInt_t ReservedEquation3;
uint16_t MinVoltageUlvGfx;
uint16_t MinVoltageUlvSoc;
uint32_t Reserved[15];
uint32_t Reserved[14];

View File

@ -350,19 +350,44 @@ int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type,
{
uint8_t tmds_oen = enable ? 0 : DP_DUAL_MODE_TMDS_DISABLE;
ssize_t ret;
int retry;
if (type < DRM_DP_DUAL_MODE_TYPE2_DVI)
return 0;
ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
&tmds_oen, sizeof(tmds_oen));
if (ret) {
DRM_DEBUG_KMS("Failed to %s TMDS output buffers\n",
enable ? "enable" : "disable");
return ret;
/*
* LSPCON adapters in low-power state may ignore the first write, so
* read back and verify the written value a few times.
*/
for (retry = 0; retry < 3; retry++) {
uint8_t tmp;
ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
&tmds_oen, sizeof(tmds_oen));
if (ret) {
DRM_DEBUG_KMS("Failed to %s TMDS output buffers (%d attempts)\n",
enable ? "enable" : "disable",
retry + 1);
return ret;
}
ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_TMDS_OEN,
&tmp, sizeof(tmp));
if (ret) {
DRM_DEBUG_KMS("I2C read failed during TMDS output buffer %s (%d attempts)\n",
enable ? "enabling" : "disabling",
retry + 1);
return ret;
}
if (tmp == tmds_oen)
return 0;
}
return 0;
DRM_DEBUG_KMS("I2C write value mismatch during TMDS output buffer %s\n",
enable ? "enabling" : "disabling");
return -EIO;
}
EXPORT_SYMBOL(drm_dp_dual_mode_set_tmds_output);

View File

@ -18,6 +18,7 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <uapi/drm/exynos_drm.h>
#include "exynos_drm_drv.h"
@ -26,20 +27,6 @@
#include "exynos_drm_iommu.h"
#include "exynos_drm_crtc.h"
#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb)
/*
* exynos specific framebuffer structure.
*
* @fb: drm framebuffer obejct.
* @exynos_gem: array of exynos specific gem object containing a gem object.
*/
struct exynos_drm_fb {
struct drm_framebuffer fb;
struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
dma_addr_t dma_addr[MAX_FB_BUFFER];
};
static int check_fb_gem_memory_type(struct drm_device *drm_dev,
struct exynos_drm_gem *exynos_gem)
{
@ -66,40 +53,9 @@ static int check_fb_gem_memory_type(struct drm_device *drm_dev,
return 0;
}
static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
unsigned int i;
drm_framebuffer_cleanup(fb);
for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem); i++) {
struct drm_gem_object *obj;
if (exynos_fb->exynos_gem[i] == NULL)
continue;
obj = &exynos_fb->exynos_gem[i]->base;
drm_gem_object_unreference_unlocked(obj);
}
kfree(exynos_fb);
exynos_fb = NULL;
}
static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned int *handle)
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
return drm_gem_handle_create(file_priv,
&exynos_fb->exynos_gem[0]->base, handle);
}
static const struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
.destroy = exynos_drm_fb_destroy,
.create_handle = exynos_drm_fb_create_handle,
.destroy = drm_gem_fb_destroy,
.create_handle = drm_gem_fb_create_handle,
};
struct drm_framebuffer *
@ -108,12 +64,12 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
struct exynos_drm_gem **exynos_gem,
int count)
{
struct exynos_drm_fb *exynos_fb;
struct drm_framebuffer *fb;
int i;
int ret;
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb)
fb = kzalloc(sizeof(*fb), GFP_KERNEL);
if (!fb)
return ERR_PTR(-ENOMEM);
for (i = 0; i < count; i++) {
@ -121,23 +77,21 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
if (ret < 0)
goto err;
exynos_fb->exynos_gem[i] = exynos_gem[i];
exynos_fb->dma_addr[i] = exynos_gem[i]->dma_addr
+ mode_cmd->offsets[i];
fb->obj[i] = &exynos_gem[i]->base;
}
drm_helper_mode_fill_fb_struct(dev, &exynos_fb->fb, mode_cmd);
drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs);
if (ret < 0) {
DRM_ERROR("failed to initialize framebuffer\n");
goto err;
}
return &exynos_fb->fb;
return fb;
err:
kfree(exynos_fb);
kfree(fb);
return ERR_PTR(ret);
}
@ -191,12 +145,13 @@ err:
dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
struct exynos_drm_gem *exynos_gem;
if (WARN_ON_ONCE(index >= MAX_FB_BUFFER))
return 0;
return exynos_fb->dma_addr[index];
exynos_gem = to_exynos_gem(fb->obj[index]);
return exynos_gem->dma_addr + fb->offsets[index];
}
static struct drm_mode_config_helper_funcs exynos_drm_mode_config_helpers = {

View File

@ -1080,6 +1080,7 @@ static int cmd_handler_mi_user_interrupt(struct parser_exec_state *s)
{
set_bit(cmd_interrupt_events[s->ring_id].mi_user_interrupt,
s->workload->pending_events);
patch_value(s, cmd_ptr(s, 0), MI_NOOP);
return 0;
}

View File

@ -169,6 +169,8 @@ static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = {
static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
int pipe;
vgpu_vreg_t(vgpu, SDEISR) &= ~(SDE_PORTB_HOTPLUG_CPT |
SDE_PORTC_HOTPLUG_CPT |
SDE_PORTD_HOTPLUG_CPT);
@ -267,6 +269,14 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
if (IS_BROADWELL(dev_priv))
vgpu_vreg_t(vgpu, PCH_ADPA) &= ~ADPA_CRT_HOTPLUG_MONITOR_MASK;
/* Disable Primary/Sprite/Cursor plane */
for_each_pipe(dev_priv, pipe) {
vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISPLAY_PLANE_ENABLE;
vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE;
vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~CURSOR_MODE;
vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= CURSOR_MODE_DISABLE;
}
vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= PIPECONF_ENABLE;
}

View File

@ -323,6 +323,7 @@ static void update_fb_info(struct vfio_device_gfx_plane_info *gvt_dmabuf,
struct intel_vgpu_fb_info *fb_info)
{
gvt_dmabuf->drm_format = fb_info->drm_format;
gvt_dmabuf->drm_format_mod = fb_info->drm_format_mod;
gvt_dmabuf->width = fb_info->width;
gvt_dmabuf->height = fb_info->height;
gvt_dmabuf->stride = fb_info->stride;

View File

@ -245,16 +245,13 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
plane->hw_format = fmt;
plane->base = vgpu_vreg_t(vgpu, DSPSURF(pipe)) & I915_GTT_PAGE_MASK;
if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0)) {
gvt_vgpu_err("invalid gma address: %lx\n",
(unsigned long)plane->base);
if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
return -EINVAL;
}
plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) {
gvt_vgpu_err("invalid gma address: %lx\n",
(unsigned long)plane->base);
gvt_vgpu_err("Translate primary plane gma 0x%x to gpa fail\n",
plane->base);
return -EINVAL;
}
@ -371,16 +368,13 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu,
alpha_plane, alpha_force);
plane->base = vgpu_vreg_t(vgpu, CURBASE(pipe)) & I915_GTT_PAGE_MASK;
if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0)) {
gvt_vgpu_err("invalid gma address: %lx\n",
(unsigned long)plane->base);
if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
return -EINVAL;
}
plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) {
gvt_vgpu_err("invalid gma address: %lx\n",
(unsigned long)plane->base);
gvt_vgpu_err("Translate cursor plane gma 0x%x to gpa fail\n",
plane->base);
return -EINVAL;
}
@ -476,16 +470,13 @@ int intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu,
plane->drm_format = drm_format;
plane->base = vgpu_vreg_t(vgpu, SPRSURF(pipe)) & I915_GTT_PAGE_MASK;
if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0)) {
gvt_vgpu_err("invalid gma address: %lx\n",
(unsigned long)plane->base);
if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
return -EINVAL;
}
plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) {
gvt_vgpu_err("invalid gma address: %lx\n",
(unsigned long)plane->base);
gvt_vgpu_err("Translate sprite plane gma 0x%x to gpa fail\n",
plane->base);
return -EINVAL;
}

View File

@ -530,6 +530,16 @@ static void ggtt_set_guest_entry(struct intel_vgpu_mm *mm,
false, 0, mm->vgpu);
}
static void ggtt_get_host_entry(struct intel_vgpu_mm *mm,
struct intel_gvt_gtt_entry *entry, unsigned long index)
{
struct intel_gvt_gtt_pte_ops *pte_ops = mm->vgpu->gvt->gtt.pte_ops;
GEM_BUG_ON(mm->type != INTEL_GVT_MM_GGTT);
pte_ops->get_entry(NULL, entry, index, false, 0, mm->vgpu);
}
static void ggtt_set_host_entry(struct intel_vgpu_mm *mm,
struct intel_gvt_gtt_entry *entry, unsigned long index)
{
@ -1818,6 +1828,18 @@ int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
return ret;
}
static void ggtt_invalidate_pte(struct intel_vgpu *vgpu,
struct intel_gvt_gtt_entry *entry)
{
struct intel_gvt_gtt_pte_ops *pte_ops = vgpu->gvt->gtt.pte_ops;
unsigned long pfn;
pfn = pte_ops->get_pfn(entry);
if (pfn != vgpu->gvt->gtt.scratch_mfn)
intel_gvt_hypervisor_dma_unmap_guest_page(vgpu,
pfn << PAGE_SHIFT);
}
static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
void *p_data, unsigned int bytes)
{
@ -1844,10 +1866,10 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
bytes);
m = e;
if (ops->test_present(&e)) {
gfn = ops->get_pfn(&e);
m = e;
/* one PTE update may be issued in multiple writes and the
* first write may not construct a valid gfn
@ -1868,8 +1890,12 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
ops->set_pfn(&m, gvt->gtt.scratch_mfn);
} else
ops->set_pfn(&m, dma_addr >> PAGE_SHIFT);
} else
} else {
ggtt_get_host_entry(ggtt_mm, &m, g_gtt_index);
ggtt_invalidate_pte(vgpu, &m);
ops->set_pfn(&m, gvt->gtt.scratch_mfn);
ops->clear_present(&m);
}
out:
ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index);
@ -2030,7 +2056,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
return PTR_ERR(gtt->ggtt_mm);
}
intel_vgpu_reset_ggtt(vgpu);
intel_vgpu_reset_ggtt(vgpu, false);
return create_scratch_page_tree(vgpu);
}
@ -2315,17 +2341,19 @@ void intel_vgpu_invalidate_ppgtt(struct intel_vgpu *vgpu)
/**
* intel_vgpu_reset_ggtt - reset the GGTT entry
* @vgpu: a vGPU
* @invalidate_old: invalidate old entries
*
* This function is called at the vGPU create stage
* to reset all the GGTT entries.
*
*/
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu, bool invalidate_old)
{
struct intel_gvt *gvt = vgpu->gvt;
struct drm_i915_private *dev_priv = gvt->dev_priv;
struct intel_gvt_gtt_pte_ops *pte_ops = vgpu->gvt->gtt.pte_ops;
struct intel_gvt_gtt_entry entry = {.type = GTT_TYPE_GGTT_PTE};
struct intel_gvt_gtt_entry old_entry;
u32 index;
u32 num_entries;
@ -2334,13 +2362,23 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
index = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT;
num_entries = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT;
while (num_entries--)
while (num_entries--) {
if (invalidate_old) {
ggtt_get_host_entry(vgpu->gtt.ggtt_mm, &old_entry, index);
ggtt_invalidate_pte(vgpu, &old_entry);
}
ggtt_set_host_entry(vgpu->gtt.ggtt_mm, &entry, index++);
}
index = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT;
num_entries = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT;
while (num_entries--)
while (num_entries--) {
if (invalidate_old) {
ggtt_get_host_entry(vgpu->gtt.ggtt_mm, &old_entry, index);
ggtt_invalidate_pte(vgpu, &old_entry);
}
ggtt_set_host_entry(vgpu->gtt.ggtt_mm, &entry, index++);
}
ggtt_invalidate(dev_priv);
}
@ -2360,5 +2398,5 @@ void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu)
* removing the shadow pages.
*/
intel_vgpu_destroy_all_ppgtt_mm(vgpu);
intel_vgpu_reset_ggtt(vgpu);
intel_vgpu_reset_ggtt(vgpu, true);
}

View File

@ -193,7 +193,7 @@ struct intel_vgpu_gtt {
extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu, bool invalidate_old);
void intel_vgpu_invalidate_ppgtt(struct intel_vgpu *vgpu);
extern int intel_gvt_init_gtt(struct intel_gvt *gvt);

View File

@ -1150,6 +1150,7 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)
switch (notification) {
case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE:
root_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY;
/* fall through */
case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE:
mm = intel_vgpu_get_ppgtt_mm(vgpu, root_entry_type, pdps);
return PTR_ERR_OR_ZERO(mm);

View File

@ -1301,7 +1301,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
}
return 0;
return -ENOTTY;
}
static ssize_t

View File

@ -1105,30 +1105,32 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
ret = i915_ggtt_probe_hw(dev_priv);
if (ret)
return ret;
goto err_perf;
/* WARNING: Apparently we must kick fbdev drivers before vgacon,
* otherwise the vga fbdev driver falls over. */
/*
* WARNING: Apparently we must kick fbdev drivers before vgacon,
* otherwise the vga fbdev driver falls over.
*/
ret = i915_kick_out_firmware_fb(dev_priv);
if (ret) {
DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
goto out_ggtt;
goto err_ggtt;
}
ret = i915_kick_out_vgacon(dev_priv);
if (ret) {
DRM_ERROR("failed to remove conflicting VGA console\n");
goto out_ggtt;
goto err_ggtt;
}
ret = i915_ggtt_init_hw(dev_priv);
if (ret)
return ret;
goto err_ggtt;
ret = i915_ggtt_enable_hw(dev_priv);
if (ret) {
DRM_ERROR("failed to enable GGTT\n");
goto out_ggtt;
goto err_ggtt;
}
pci_set_master(pdev);
@ -1139,7 +1141,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
if (ret) {
DRM_ERROR("failed to set DMA mask\n");
goto out_ggtt;
goto err_ggtt;
}
}
@ -1157,7 +1159,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
if (ret) {
DRM_ERROR("failed to set DMA mask\n");
goto out_ggtt;
goto err_ggtt;
}
}
@ -1190,13 +1192,14 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
ret = intel_gvt_init(dev_priv);
if (ret)
goto out_ggtt;
goto err_ggtt;
return 0;
out_ggtt:
err_ggtt:
i915_ggtt_cleanup_hw(dev_priv);
err_perf:
i915_perf_fini(dev_priv);
return ret;
}

View File

@ -728,7 +728,7 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
err = radix_tree_insert(handles_vma, handle, vma);
if (unlikely(err)) {
kfree(lut);
kmem_cache_free(eb->i915->luts, lut);
goto err_obj;
}

View File

@ -473,20 +473,37 @@ static u64 get_rc6(struct drm_i915_private *i915)
spin_lock_irqsave(&i915->pmu.lock, flags);
spin_lock(&kdev->power.lock);
if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur)
i915->pmu.suspended_jiffies_last =
kdev->power.suspended_jiffies;
/*
* After the above branch intel_runtime_pm_get_if_in_use failed
* to get the runtime PM reference we cannot assume we are in
* runtime suspend since we can either: a) race with coming out
* of it before we took the power.lock, or b) there are other
* states than suspended which can bring us here.
*
* We need to double-check that we are indeed currently runtime
* suspended and if not we cannot do better than report the last
* known RC6 value.
*/
if (kdev->power.runtime_status == RPM_SUSPENDED) {
if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur)
i915->pmu.suspended_jiffies_last =
kdev->power.suspended_jiffies;
val = kdev->power.suspended_jiffies -
i915->pmu.suspended_jiffies_last;
val += jiffies - kdev->power.accounting_timestamp;
val = kdev->power.suspended_jiffies -
i915->pmu.suspended_jiffies_last;
val += jiffies - kdev->power.accounting_timestamp;
val = jiffies_to_nsecs(val);
val += i915->pmu.sample[__I915_SAMPLE_RC6].cur;
i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val;
} else if (i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) {
val = i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur;
} else {
val = i915->pmu.sample[__I915_SAMPLE_RC6].cur;
}
spin_unlock(&kdev->power.lock);
val = jiffies_to_nsecs(val);
val += i915->pmu.sample[__I915_SAMPLE_RC6].cur;
i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val;
spin_unlock_irqrestore(&i915->pmu.lock, flags);
}

View File

@ -729,7 +729,7 @@ static void i915_audio_component_codec_wake_override(struct device *kdev,
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
u32 tmp;
if (!IS_GEN9_BC(dev_priv))
if (!IS_GEN9(dev_priv))
return;
i915_audio_component_get_power(kdev);

View File

@ -1256,7 +1256,6 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
return;
aux_channel = child->aux_channel;
ddc_pin = child->ddc_pin;
is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
@ -1303,9 +1302,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));
if (is_dvi) {
info->alternate_ddc_pin = map_ddc_pin(dev_priv, ddc_pin);
sanitize_ddc_pin(dev_priv, port);
ddc_pin = map_ddc_pin(dev_priv, child->ddc_pin);
if (intel_gmbus_is_valid_pin(dev_priv, ddc_pin)) {
info->alternate_ddc_pin = ddc_pin;
sanitize_ddc_pin(dev_priv, port);
} else {
DRM_DEBUG_KMS("Port %c has invalid DDC pin %d, "
"sticking to defaults\n",
port_name(port), ddc_pin);
}
}
if (is_dp) {

View File

@ -577,6 +577,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* know the next preemption status we see corresponds
* to this ELSP update.
*/
GEM_BUG_ON(!execlists_is_active(execlists,
EXECLISTS_ACTIVE_USER));
GEM_BUG_ON(!port_count(&port[0]));
if (port_count(&port[0]) > 1)
goto unlock;
@ -738,6 +740,8 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists)
memset(port, 0, sizeof(*port));
port++;
}
execlists_clear_active(execlists, EXECLISTS_ACTIVE_USER);
}
static void execlists_cancel_requests(struct intel_engine_cs *engine)
@ -1001,6 +1005,11 @@ static void execlists_submission_tasklet(unsigned long data)
if (fw)
intel_uncore_forcewake_put(dev_priv, execlists->fw_domains);
/* If the engine is now idle, so should be the flag; and vice versa. */
GEM_BUG_ON(execlists_is_active(&engine->execlists,
EXECLISTS_ACTIVE_USER) ==
!port_isset(engine->execlists.port));
}
static void queue_request(struct intel_engine_cs *engine,

View File

@ -195,6 +195,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
vc4_bo_set_label(obj, -1);
if (bo->validated_shader) {
kfree(bo->validated_shader->uniform_addr_offsets);
kfree(bo->validated_shader->texture_samples);
kfree(bo->validated_shader);
bo->validated_shader = NULL;
@ -591,6 +592,7 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
}
if (bo->validated_shader) {
kfree(bo->validated_shader->uniform_addr_offsets);
kfree(bo->validated_shader->texture_samples);
kfree(bo->validated_shader);
bo->validated_shader = NULL;

View File

@ -942,6 +942,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
fail:
kfree(validation_state.branch_targets);
if (validated_shader) {
kfree(validated_shader->uniform_addr_offsets);
kfree(validated_shader->texture_samples);
kfree(validated_shader);
}

View File

@ -1660,8 +1660,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
} /* switch(bond_mode) */
#ifdef CONFIG_NET_POLL_CONTROLLER
slave_dev->npinfo = bond->dev->npinfo;
if (slave_dev->npinfo) {
if (bond->dev->npinfo) {
if (slave_enable_netpoll(new_slave)) {
netdev_info(bond_dev, "master_dev is using netpoll, but new slave device does not support netpoll\n");
res = -EBUSY;

View File

@ -1321,6 +1321,10 @@
#define MDIO_VEND2_AN_STAT 0x8002
#endif
#ifndef MDIO_VEND2_PMA_CDR_CONTROL
#define MDIO_VEND2_PMA_CDR_CONTROL 0x8056
#endif
#ifndef MDIO_CTRL1_SPEED1G
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
#endif
@ -1369,6 +1373,10 @@
#define XGBE_AN_CL37_TX_CONFIG_MASK 0x08
#define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100
#define XGBE_PMA_CDR_TRACK_EN_MASK 0x01
#define XGBE_PMA_CDR_TRACK_EN_OFF 0x00
#define XGBE_PMA_CDR_TRACK_EN_ON 0x01
/* Bit setting and getting macros
* The get macro will extract the current bit field value from within
* the variable

View File

@ -519,6 +519,22 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
"debugfs_create_file failed\n");
}
if (pdata->vdata->an_cdr_workaround) {
pfile = debugfs_create_bool("an_cdr_workaround", 0600,
pdata->xgbe_debugfs,
&pdata->debugfs_an_cdr_workaround);
if (!pfile)
netdev_err(pdata->netdev,
"debugfs_create_bool failed\n");
pfile = debugfs_create_bool("an_cdr_track_early", 0600,
pdata->xgbe_debugfs,
&pdata->debugfs_an_cdr_track_early);
if (!pfile)
netdev_err(pdata->netdev,
"debugfs_create_bool failed\n");
}
kfree(buf);
}

View File

@ -349,6 +349,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata)
XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
/* Call MDIO/PHY initialization routine */
pdata->debugfs_an_cdr_workaround = pdata->vdata->an_cdr_workaround;
ret = pdata->phy_if.phy_init(pdata);
if (ret)
return ret;

View File

@ -432,11 +432,16 @@ static void xgbe_an73_disable(struct xgbe_prv_data *pdata)
xgbe_an73_set(pdata, false, false);
xgbe_an73_disable_interrupts(pdata);
pdata->an_start = 0;
netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n");
}
static void xgbe_an_restart(struct xgbe_prv_data *pdata)
{
if (pdata->phy_if.phy_impl.an_pre)
pdata->phy_if.phy_impl.an_pre(pdata);
switch (pdata->an_mode) {
case XGBE_AN_MODE_CL73:
case XGBE_AN_MODE_CL73_REDRV:
@ -453,6 +458,9 @@ static void xgbe_an_restart(struct xgbe_prv_data *pdata)
static void xgbe_an_disable(struct xgbe_prv_data *pdata)
{
if (pdata->phy_if.phy_impl.an_post)
pdata->phy_if.phy_impl.an_post(pdata);
switch (pdata->an_mode) {
case XGBE_AN_MODE_CL73:
case XGBE_AN_MODE_CL73_REDRV:
@ -505,11 +513,11 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
reg);
if (pdata->phy_if.phy_impl.kr_training_post)
pdata->phy_if.phy_impl.kr_training_post(pdata);
netif_dbg(pdata, link, pdata->netdev,
"KR training initiated\n");
if (pdata->phy_if.phy_impl.kr_training_post)
pdata->phy_if.phy_impl.kr_training_post(pdata);
}
return XGBE_AN_PAGE_RECEIVED;
@ -637,11 +645,11 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
return XGBE_AN_NO_LINK;
}
xgbe_an73_disable(pdata);
xgbe_an_disable(pdata);
xgbe_switch_mode(pdata);
xgbe_an73_restart(pdata);
xgbe_an_restart(pdata);
return XGBE_AN_INCOMPAT_LINK;
}
@ -820,6 +828,9 @@ static void xgbe_an37_state_machine(struct xgbe_prv_data *pdata)
pdata->an_result = pdata->an_state;
pdata->an_state = XGBE_AN_READY;
if (pdata->phy_if.phy_impl.an_post)
pdata->phy_if.phy_impl.an_post(pdata);
netif_dbg(pdata, link, pdata->netdev, "CL37 AN result: %s\n",
xgbe_state_as_string(pdata->an_result));
}
@ -903,6 +914,9 @@ again:
pdata->kx_state = XGBE_RX_BPA;
pdata->an_start = 0;
if (pdata->phy_if.phy_impl.an_post)
pdata->phy_if.phy_impl.an_post(pdata);
netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n",
xgbe_state_as_string(pdata->an_result));
}

View File

@ -456,6 +456,7 @@ static const struct xgbe_version_data xgbe_v2a = {
.irq_reissue_support = 1,
.tx_desc_prefetch = 5,
.rx_desc_prefetch = 5,
.an_cdr_workaround = 1,
};
static const struct xgbe_version_data xgbe_v2b = {
@ -470,6 +471,7 @@ static const struct xgbe_version_data xgbe_v2b = {
.irq_reissue_support = 1,
.tx_desc_prefetch = 5,
.rx_desc_prefetch = 5,
.an_cdr_workaround = 1,
};
static const struct pci_device_id xgbe_pci_table[] = {

View File

@ -147,6 +147,14 @@
/* Rate-change complete wait/retry count */
#define XGBE_RATECHANGE_COUNT 500
/* CDR delay values for KR support (in usec) */
#define XGBE_CDR_DELAY_INIT 10000
#define XGBE_CDR_DELAY_INC 10000
#define XGBE_CDR_DELAY_MAX 100000
/* RRC frequency during link status check */
#define XGBE_RRC_FREQUENCY 10
enum xgbe_port_mode {
XGBE_PORT_MODE_RSVD = 0,
XGBE_PORT_MODE_BACKPLANE,
@ -245,6 +253,10 @@ enum xgbe_sfp_speed {
#define XGBE_SFP_BASE_VENDOR_SN 4
#define XGBE_SFP_BASE_VENDOR_SN_LEN 16
#define XGBE_SFP_EXTD_OPT1 1
#define XGBE_SFP_EXTD_OPT1_RX_LOS BIT(1)
#define XGBE_SFP_EXTD_OPT1_TX_FAULT BIT(3)
#define XGBE_SFP_EXTD_DIAG 28
#define XGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2)
@ -324,6 +336,7 @@ struct xgbe_phy_data {
unsigned int sfp_gpio_address;
unsigned int sfp_gpio_mask;
unsigned int sfp_gpio_inputs;
unsigned int sfp_gpio_rx_los;
unsigned int sfp_gpio_tx_fault;
unsigned int sfp_gpio_mod_absent;
@ -355,6 +368,10 @@ struct xgbe_phy_data {
unsigned int redrv_addr;
unsigned int redrv_lane;
unsigned int redrv_model;
/* KR AN support */
unsigned int phy_cdr_notrack;
unsigned int phy_cdr_delay;
};
/* I2C, MDIO and GPIO lines are muxed, so only one device at a time */
@ -974,6 +991,49 @@ static void xgbe_phy_sfp_external_phy(struct xgbe_prv_data *pdata)
phy_data->sfp_phy_avail = 1;
}
static bool xgbe_phy_check_sfp_rx_los(struct xgbe_phy_data *phy_data)
{
u8 *sfp_extd = phy_data->sfp_eeprom.extd;
if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_RX_LOS))
return false;
if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS)
return false;
if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_rx_los))
return true;
return false;
}
static bool xgbe_phy_check_sfp_tx_fault(struct xgbe_phy_data *phy_data)
{
u8 *sfp_extd = phy_data->sfp_eeprom.extd;
if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_TX_FAULT))
return false;
if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT)
return false;
if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_tx_fault))
return true;
return false;
}
static bool xgbe_phy_check_sfp_mod_absent(struct xgbe_phy_data *phy_data)
{
if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT)
return false;
if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_mod_absent))
return true;
return false;
}
static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
@ -1019,6 +1079,10 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
if (sfp_base[XGBE_SFP_BASE_EXT_ID] != XGBE_SFP_EXT_ID_SFP)
return;
/* Update transceiver signals (eeprom extd/options) */
phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data);
phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data);
if (xgbe_phy_sfp_parse_quirks(pdata))
return;
@ -1184,7 +1248,6 @@ put:
static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int gpio_input;
u8 gpio_reg, gpio_ports[2];
int ret;
@ -1199,23 +1262,9 @@ static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata)
return;
}
gpio_input = (gpio_ports[1] << 8) | gpio_ports[0];
phy_data->sfp_gpio_inputs = (gpio_ports[1] << 8) | gpio_ports[0];
if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT) {
/* No GPIO, just assume the module is present for now */
phy_data->sfp_mod_absent = 0;
} else {
if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent)))
phy_data->sfp_mod_absent = 0;
}
if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS) &&
(gpio_input & (1 << phy_data->sfp_gpio_rx_los)))
phy_data->sfp_rx_los = 1;
if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT) &&
(gpio_input & (1 << phy_data->sfp_gpio_tx_fault)))
phy_data->sfp_tx_fault = 1;
phy_data->sfp_mod_absent = xgbe_phy_check_sfp_mod_absent(phy_data);
}
static void xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata)
@ -2361,7 +2410,7 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
return 1;
/* No link, attempt a receiver reset cycle */
if (phy_data->rrc_count++) {
if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) {
phy_data->rrc_count = 0;
xgbe_phy_rrc(pdata);
}
@ -2669,6 +2718,103 @@ static bool xgbe_phy_port_enabled(struct xgbe_prv_data *pdata)
return true;
}
static void xgbe_phy_cdr_track(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
if (!pdata->debugfs_an_cdr_workaround)
return;
if (!phy_data->phy_cdr_notrack)
return;
usleep_range(phy_data->phy_cdr_delay,
phy_data->phy_cdr_delay + 500);
XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL,
XGBE_PMA_CDR_TRACK_EN_MASK,
XGBE_PMA_CDR_TRACK_EN_ON);
phy_data->phy_cdr_notrack = 0;
}
static void xgbe_phy_cdr_notrack(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
if (!pdata->debugfs_an_cdr_workaround)
return;
if (phy_data->phy_cdr_notrack)
return;
XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL,
XGBE_PMA_CDR_TRACK_EN_MASK,
XGBE_PMA_CDR_TRACK_EN_OFF);
xgbe_phy_rrc(pdata);
phy_data->phy_cdr_notrack = 1;
}
static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
{
if (!pdata->debugfs_an_cdr_track_early)
xgbe_phy_cdr_track(pdata);
}
static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
{
if (pdata->debugfs_an_cdr_track_early)
xgbe_phy_cdr_track(pdata);
}
static void xgbe_phy_an_post(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
switch (pdata->an_mode) {
case XGBE_AN_MODE_CL73:
case XGBE_AN_MODE_CL73_REDRV:
if (phy_data->cur_mode != XGBE_MODE_KR)
break;
xgbe_phy_cdr_track(pdata);
switch (pdata->an_result) {
case XGBE_AN_READY:
case XGBE_AN_COMPLETE:
break;
default:
if (phy_data->phy_cdr_delay < XGBE_CDR_DELAY_MAX)
phy_data->phy_cdr_delay += XGBE_CDR_DELAY_INC;
else
phy_data->phy_cdr_delay = XGBE_CDR_DELAY_INIT;
break;
}
break;
default:
break;
}
}
static void xgbe_phy_an_pre(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
switch (pdata->an_mode) {
case XGBE_AN_MODE_CL73:
case XGBE_AN_MODE_CL73_REDRV:
if (phy_data->cur_mode != XGBE_MODE_KR)
break;
xgbe_phy_cdr_notrack(pdata);
break;
default:
break;
}
}
static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
@ -2680,6 +2826,9 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
xgbe_phy_sfp_reset(phy_data);
xgbe_phy_sfp_mod_absent(pdata);
/* Reset CDR support */
xgbe_phy_cdr_track(pdata);
/* Power off the PHY */
xgbe_phy_power_off(pdata);
@ -2712,6 +2861,9 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata)
/* Start in highest supported mode */
xgbe_phy_set_mode(pdata, phy_data->start_mode);
/* Reset CDR support */
xgbe_phy_cdr_track(pdata);
/* After starting the I2C controller, we can check for an SFP */
switch (phy_data->port_mode) {
case XGBE_PORT_MODE_SFP:
@ -3019,6 +3171,8 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
}
}
phy_data->phy_cdr_delay = XGBE_CDR_DELAY_INIT;
/* Register for driving external PHYs */
mii = devm_mdiobus_alloc(pdata->dev);
if (!mii) {
@ -3071,4 +3225,10 @@ void xgbe_init_function_ptrs_phy_v2(struct xgbe_phy_if *phy_if)
phy_impl->an_advertising = xgbe_phy_an_advertising;
phy_impl->an_outcome = xgbe_phy_an_outcome;
phy_impl->an_pre = xgbe_phy_an_pre;
phy_impl->an_post = xgbe_phy_an_post;
phy_impl->kr_training_pre = xgbe_phy_kr_training_pre;
phy_impl->kr_training_post = xgbe_phy_kr_training_post;
}

View File

@ -833,6 +833,7 @@ struct xgbe_hw_if {
/* This structure represents implementation specific routines for an
* implementation of a PHY. All routines are required unless noted below.
* Optional routines:
* an_pre, an_post
* kr_training_pre, kr_training_post
*/
struct xgbe_phy_impl_if {
@ -875,6 +876,10 @@ struct xgbe_phy_impl_if {
/* Process results of auto-negotiation */
enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *);
/* Pre/Post auto-negotiation support */
void (*an_pre)(struct xgbe_prv_data *);
void (*an_post)(struct xgbe_prv_data *);
/* Pre/Post KR training enablement support */
void (*kr_training_pre)(struct xgbe_prv_data *);
void (*kr_training_post)(struct xgbe_prv_data *);
@ -989,6 +994,7 @@ struct xgbe_version_data {
unsigned int irq_reissue_support;
unsigned int tx_desc_prefetch;
unsigned int rx_desc_prefetch;
unsigned int an_cdr_workaround;
};
struct xgbe_vxlan_data {
@ -1257,6 +1263,9 @@ struct xgbe_prv_data {
unsigned int debugfs_xprop_reg;
unsigned int debugfs_xi2c_reg;
bool debugfs_an_cdr_workaround;
bool debugfs_an_cdr_track_early;
};
/* Function prototypes*/

View File

@ -1128,7 +1128,7 @@ static void clean_rx_pools(struct ibmvnic_adapter *adapter)
if (!adapter->rx_pool)
return;
rx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
rx_scrqs = adapter->num_active_rx_pools;
rx_entries = adapter->req_rx_add_entries_per_subcrq;
/* Free any remaining skbs in the rx buffer pools */
@ -1177,7 +1177,7 @@ static void clean_tx_pools(struct ibmvnic_adapter *adapter)
if (!adapter->tx_pool || !adapter->tso_pool)
return;
tx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
tx_scrqs = adapter->num_active_tx_pools;
/* Free any remaining skbs in the tx buffer pools */
for (i = 0; i < tx_scrqs; i++) {

View File

@ -586,7 +586,7 @@ struct ice_sw_rule_lg_act {
#define ICE_LG_ACT_MIRROR_VSI_ID_S 3
#define ICE_LG_ACT_MIRROR_VSI_ID_M (0x3FF << ICE_LG_ACT_MIRROR_VSI_ID_S)
/* Action type = 5 - Large Action */
/* Action type = 5 - Generic Value */
#define ICE_LG_ACT_GENERIC 0x5
#define ICE_LG_ACT_GENERIC_VALUE_S 3
#define ICE_LG_ACT_GENERIC_VALUE_M (0xFFFF << ICE_LG_ACT_GENERIC_VALUE_S)

View File

@ -78,6 +78,7 @@ ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
struct ice_aq_desc desc;
enum ice_status status;
u16 flags;
u8 i;
cmd = &desc.params.mac_read;
@ -98,8 +99,16 @@ ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
return ICE_ERR_CFG;
}
ether_addr_copy(hw->port_info->mac.lan_addr, resp->mac_addr);
ether_addr_copy(hw->port_info->mac.perm_addr, resp->mac_addr);
/* A single port can report up to two (LAN and WoL) addresses */
for (i = 0; i < cmd->num_addr; i++)
if (resp[i].addr_type == ICE_AQC_MAN_MAC_ADDR_TYPE_LAN) {
ether_addr_copy(hw->port_info->mac.lan_addr,
resp[i].mac_addr);
ether_addr_copy(hw->port_info->mac.perm_addr,
resp[i].mac_addr);
break;
}
return 0;
}
@ -464,9 +473,12 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
if (status)
goto err_unroll_sched;
/* Get port MAC information */
mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp);
mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL);
/* Get MAC information */
/* A single port can report up to two (LAN and WoL) addresses */
mac_buf = devm_kcalloc(ice_hw_to_dev(hw), 2,
sizeof(struct ice_aqc_manage_mac_read_resp),
GFP_KERNEL);
mac_buf_len = 2 * sizeof(struct ice_aqc_manage_mac_read_resp);
if (!mac_buf) {
status = ICE_ERR_NO_MEMORY;

View File

@ -121,8 +121,6 @@
#define PFINT_FW_CTL_CAUSE_ENA_S 30
#define PFINT_FW_CTL_CAUSE_ENA_M BIT(PFINT_FW_CTL_CAUSE_ENA_S)
#define PFINT_OICR 0x0016CA00
#define PFINT_OICR_INTEVENT_S 0
#define PFINT_OICR_INTEVENT_M BIT(PFINT_OICR_INTEVENT_S)
#define PFINT_OICR_HLP_RDY_S 14
#define PFINT_OICR_HLP_RDY_M BIT(PFINT_OICR_HLP_RDY_S)
#define PFINT_OICR_CPM_RDY_S 15

View File

@ -1722,9 +1722,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
oicr = rd32(hw, PFINT_OICR);
ena_mask = rd32(hw, PFINT_OICR_ENA);
if (!(oicr & PFINT_OICR_INTEVENT_M))
goto ena_intr;
if (oicr & PFINT_OICR_GRST_M) {
u32 reset;
/* we have a reset warning */
@ -1782,7 +1779,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
}
ret = IRQ_HANDLED;
ena_intr:
/* re-enable interrupt causes that are not handled during this pass */
wr32(hw, PFINT_OICR_ENA, ena_mask);
if (!test_bit(__ICE_DOWN, pf->state)) {

View File

@ -751,14 +751,14 @@ ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
u16 num_added = 0;
u32 temp;
*num_nodes_added = 0;
if (!num_nodes)
return status;
if (!parent || layer < hw->sw_entry_point_layer)
return ICE_ERR_PARAM;
*num_nodes_added = 0;
/* max children per node per layer */
max_child_nodes =
le16_to_cpu(hw->layer_info[parent->tx_sched_layer].max_children);

View File

@ -1700,7 +1700,22 @@ static void igb_configure_cbs(struct igb_adapter *adapter, int queue,
WARN_ON(hw->mac.type != e1000_i210);
WARN_ON(queue < 0 || queue > 1);
if (enable) {
if (enable || queue == 0) {
/* i210 does not allow the queue 0 to be in the Strict
* Priority mode while the Qav mode is enabled, so,
* instead of disabling strict priority mode, we give
* queue 0 the maximum of credits possible.
*
* See section 8.12.19 of the i210 datasheet, "Note:
* Queue0 QueueMode must be set to 1b when
* TransmitMode is set to Qav."
*/
if (queue == 0 && !enable) {
/* max "linkspeed" idleslope in kbps */
idleslope = 1000000;
hicredit = ETH_FRAME_LEN;
}
set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_HIGH);
set_queue_mode(hw, queue, QUEUE_MODE_STREAM_RESERVATION);

View File

@ -3420,7 +3420,7 @@ static int ixgbevf_setup_all_tx_resources(struct ixgbevf_adapter *adapter)
if (!err)
continue;
hw_dbg(&adapter->hw, "Allocation for XDP Queue %u failed\n", j);
break;
goto err_setup_tx;
}
return 0;

View File

@ -3999,29 +3999,6 @@ static void efx_ef10_prepare_flr(struct efx_nic *efx)
atomic_set(&efx->active_queues, 0);
}
static bool efx_ef10_filter_equal(const struct efx_filter_spec *left,
const struct efx_filter_spec *right)
{
if ((left->match_flags ^ right->match_flags) |
((left->flags ^ right->flags) &
(EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)))
return false;
return memcmp(&left->outer_vid, &right->outer_vid,
sizeof(struct efx_filter_spec) -
offsetof(struct efx_filter_spec, outer_vid)) == 0;
}
static unsigned int efx_ef10_filter_hash(const struct efx_filter_spec *spec)
{
BUILD_BUG_ON(offsetof(struct efx_filter_spec, outer_vid) & 3);
return jhash2((const u32 *)&spec->outer_vid,
(sizeof(struct efx_filter_spec) -
offsetof(struct efx_filter_spec, outer_vid)) / 4,
0);
/* XXX should we randomise the initval? */
}
/* Decide whether a filter should be exclusive or else should allow
* delivery to additional recipients. Currently we decide that
* filters for specific local unicast MAC and IP addresses are
@ -4346,7 +4323,7 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
goto out_unlock;
match_pri = rc;
hash = efx_ef10_filter_hash(spec);
hash = efx_filter_spec_hash(spec);
is_mc_recip = efx_filter_is_mc_recipient(spec);
if (is_mc_recip)
bitmap_zero(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT);
@ -4378,7 +4355,7 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
if (!saved_spec) {
if (ins_index < 0)
ins_index = i;
} else if (efx_ef10_filter_equal(spec, saved_spec)) {
} else if (efx_filter_spec_equal(spec, saved_spec)) {
if (spec->priority < saved_spec->priority &&
spec->priority != EFX_FILTER_PRI_AUTO) {
rc = -EPERM;
@ -4762,27 +4739,62 @@ static s32 efx_ef10_filter_get_rx_ids(struct efx_nic *efx,
static bool efx_ef10_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
unsigned int filter_idx)
{
struct efx_filter_spec *spec, saved_spec;
struct efx_ef10_filter_table *table;
struct efx_filter_spec *spec;
bool ret;
struct efx_arfs_rule *rule = NULL;
bool ret = true, force = false;
u16 arfs_id;
down_read(&efx->filter_sem);
table = efx->filter_state;
down_write(&table->lock);
spec = efx_ef10_filter_entry_spec(table, filter_idx);
if (!spec || spec->priority != EFX_FILTER_PRI_HINT) {
ret = true;
if (!spec || spec->priority != EFX_FILTER_PRI_HINT)
goto out_unlock;
}
if (!rps_may_expire_flow(efx->net_dev, spec->dmaq_id, flow_id, 0)) {
spin_lock_bh(&efx->rps_hash_lock);
if (!efx->rps_hash_table) {
/* In the absence of the table, we always return 0 to ARFS. */
arfs_id = 0;
} else {
rule = efx_rps_hash_find(efx, spec);
if (!rule)
/* ARFS table doesn't know of this filter, so remove it */
goto expire;
arfs_id = rule->arfs_id;
ret = efx_rps_check_rule(rule, filter_idx, &force);
if (force)
goto expire;
if (!ret) {
spin_unlock_bh(&efx->rps_hash_lock);
goto out_unlock;
}
}
if (!rps_may_expire_flow(efx->net_dev, spec->dmaq_id, flow_id, arfs_id))
ret = false;
goto out_unlock;
}
else if (rule)
rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING;
expire:
saved_spec = *spec; /* remove operation will kfree spec */
spin_unlock_bh(&efx->rps_hash_lock);
/* At this point (since we dropped the lock), another thread might queue
* up a fresh insertion request (but the actual insertion will be held
* up by our possession of the filter table lock). In that case, it
* will set rule->filter_id to EFX_ARFS_FILTER_ID_PENDING, meaning that
* the rule is not removed by efx_rps_hash_del() below.
*/
ret = efx_ef10_filter_remove_internal(efx, 1U << spec->priority,
filter_idx, true) == 0;
/* While we can't safely dereference rule (we dropped the lock), we can
* still test it for NULL.
*/
if (ret && rule) {
/* Expiring, so remove entry from ARFS table */
spin_lock_bh(&efx->rps_hash_lock);
efx_rps_hash_del(efx, &saved_spec);
spin_unlock_bh(&efx->rps_hash_lock);
}
out_unlock:
up_write(&table->lock);
up_read(&efx->filter_sem);

View File

@ -3059,6 +3059,10 @@ static int efx_init_struct(struct efx_nic *efx,
mutex_init(&efx->mac_lock);
#ifdef CONFIG_RFS_ACCEL
mutex_init(&efx->rps_mutex);
spin_lock_init(&efx->rps_hash_lock);
/* Failure to allocate is not fatal, but may degrade ARFS performance */
efx->rps_hash_table = kcalloc(EFX_ARFS_HASH_TABLE_SIZE,
sizeof(*efx->rps_hash_table), GFP_KERNEL);
#endif
efx->phy_op = &efx_dummy_phy_operations;
efx->mdio.dev = net_dev;
@ -3102,6 +3106,10 @@ static void efx_fini_struct(struct efx_nic *efx)
{
int i;
#ifdef CONFIG_RFS_ACCEL
kfree(efx->rps_hash_table);
#endif
for (i = 0; i < EFX_MAX_CHANNELS; i++)
kfree(efx->channel[i]);
@ -3124,6 +3132,141 @@ void efx_update_sw_stats(struct efx_nic *efx, u64 *stats)
stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops);
}
bool efx_filter_spec_equal(const struct efx_filter_spec *left,
const struct efx_filter_spec *right)
{
if ((left->match_flags ^ right->match_flags) |
((left->flags ^ right->flags) &
(EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)))
return false;
return memcmp(&left->outer_vid, &right->outer_vid,
sizeof(struct efx_filter_spec) -
offsetof(struct efx_filter_spec, outer_vid)) == 0;
}
u32 efx_filter_spec_hash(const struct efx_filter_spec *spec)
{
BUILD_BUG_ON(offsetof(struct efx_filter_spec, outer_vid) & 3);
return jhash2((const u32 *)&spec->outer_vid,
(sizeof(struct efx_filter_spec) -
offsetof(struct efx_filter_spec, outer_vid)) / 4,
0);
}
#ifdef CONFIG_RFS_ACCEL
bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx,
bool *force)
{
if (rule->filter_id == EFX_ARFS_FILTER_ID_PENDING) {
/* ARFS is currently updating this entry, leave it */
return false;
}
if (rule->filter_id == EFX_ARFS_FILTER_ID_ERROR) {
/* ARFS tried and failed to update this, so it's probably out
* of date. Remove the filter and the ARFS rule entry.
*/
rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING;
*force = true;
return true;
} else if (WARN_ON(rule->filter_id != filter_idx)) { /* can't happen */
/* ARFS has moved on, so old filter is not needed. Since we did
* not mark the rule with EFX_ARFS_FILTER_ID_REMOVING, it will
* not be removed by efx_rps_hash_del() subsequently.
*/
*force = true;
return true;
}
/* Remove it iff ARFS wants to. */
return true;
}
struct hlist_head *efx_rps_hash_bucket(struct efx_nic *efx,
const struct efx_filter_spec *spec)
{
u32 hash = efx_filter_spec_hash(spec);
WARN_ON(!spin_is_locked(&efx->rps_hash_lock));
if (!efx->rps_hash_table)
return NULL;
return &efx->rps_hash_table[hash % EFX_ARFS_HASH_TABLE_SIZE];
}
struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx,
const struct efx_filter_spec *spec)
{
struct efx_arfs_rule *rule;
struct hlist_head *head;
struct hlist_node *node;
head = efx_rps_hash_bucket(efx, spec);
if (!head)
return NULL;
hlist_for_each(node, head) {
rule = container_of(node, struct efx_arfs_rule, node);
if (efx_filter_spec_equal(spec, &rule->spec))
return rule;
}
return NULL;
}
struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx,
const struct efx_filter_spec *spec,
bool *new)
{
struct efx_arfs_rule *rule;
struct hlist_head *head;
struct hlist_node *node;
head = efx_rps_hash_bucket(efx, spec);
if (!head)
return NULL;
hlist_for_each(node, head) {
rule = container_of(node, struct efx_arfs_rule, node);
if (efx_filter_spec_equal(spec, &rule->spec)) {
*new = false;
return rule;
}
}
rule = kmalloc(sizeof(*rule), GFP_ATOMIC);
*new = true;
if (rule) {
memcpy(&rule->spec, spec, sizeof(rule->spec));
hlist_add_head(&rule->node, head);
}
return rule;
}
void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec)
{
struct efx_arfs_rule *rule;
struct hlist_head *head;
struct hlist_node *node;
head = efx_rps_hash_bucket(efx, spec);
if (WARN_ON(!head))
return;
hlist_for_each(node, head) {
rule = container_of(node, struct efx_arfs_rule, node);
if (efx_filter_spec_equal(spec, &rule->spec)) {
/* Someone already reused the entry. We know that if
* this check doesn't fire (i.e. filter_id == REMOVING)
* then the REMOVING mark was put there by our caller,
* because caller is holding a lock on filter table and
* only holders of that lock set REMOVING.
*/
if (rule->filter_id != EFX_ARFS_FILTER_ID_REMOVING)
return;
hlist_del(node);
kfree(rule);
return;
}
}
/* We didn't find it. */
WARN_ON(1);
}
#endif
/* RSS contexts. We're using linked lists and crappy O(n) algorithms, because
* (a) this is an infrequent control-plane operation and (b) n is small (max 64)
*/

View File

@ -186,6 +186,27 @@ static inline void efx_filter_rfs_expire(struct work_struct *data) {}
#endif
bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec);
bool efx_filter_spec_equal(const struct efx_filter_spec *left,
const struct efx_filter_spec *right);
u32 efx_filter_spec_hash(const struct efx_filter_spec *spec);
#ifdef CONFIG_RFS_ACCEL
bool efx_rps_check_rule(struct efx_arfs_rule *rule, unsigned int filter_idx,
bool *force);
struct efx_arfs_rule *efx_rps_hash_find(struct efx_nic *efx,
const struct efx_filter_spec *spec);
/* @new is written to indicate if entry was newly added (true) or if an old
* entry was found and returned (false).
*/
struct efx_arfs_rule *efx_rps_hash_add(struct efx_nic *efx,
const struct efx_filter_spec *spec,
bool *new);
void efx_rps_hash_del(struct efx_nic *efx, const struct efx_filter_spec *spec);
#endif
/* RSS contexts */
struct efx_rss_context *efx_alloc_rss_context_entry(struct efx_nic *efx);
struct efx_rss_context *efx_find_rss_context_entry(struct efx_nic *efx, u32 id);

View File

@ -2905,18 +2905,45 @@ bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
{
struct efx_farch_filter_state *state = efx->filter_state;
struct efx_farch_filter_table *table;
bool ret = false;
bool ret = false, force = false;
u16 arfs_id;
down_write(&state->lock);
spin_lock_bh(&efx->rps_hash_lock);
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
if (test_bit(index, table->used_bitmap) &&
table->spec[index].priority == EFX_FILTER_PRI_HINT &&
rps_may_expire_flow(efx->net_dev, table->spec[index].dmaq_id,
flow_id, 0)) {
efx_farch_filter_table_clear_entry(efx, table, index);
ret = true;
}
table->spec[index].priority == EFX_FILTER_PRI_HINT) {
struct efx_arfs_rule *rule = NULL;
struct efx_filter_spec spec;
efx_farch_filter_to_gen_spec(&spec, &table->spec[index]);
if (!efx->rps_hash_table) {
/* In the absence of the table, we always returned 0 to
* ARFS, so use the same to query it.
*/
arfs_id = 0;
} else {
rule = efx_rps_hash_find(efx, &spec);
if (!rule) {
/* ARFS table doesn't know of this filter, remove it */
force = true;
} else {
arfs_id = rule->arfs_id;
if (!efx_rps_check_rule(rule, index, &force))
goto out_unlock;
}
}
if (force || rps_may_expire_flow(efx->net_dev, spec.dmaq_id,
flow_id, arfs_id)) {
if (rule)
rule->filter_id = EFX_ARFS_FILTER_ID_REMOVING;
efx_rps_hash_del(efx, &spec);
efx_farch_filter_table_clear_entry(efx, table, index);
ret = true;
}
}
out_unlock:
spin_unlock_bh(&efx->rps_hash_lock);
up_write(&state->lock);
return ret;
}

View File

@ -734,6 +734,35 @@ struct efx_rss_context {
};
#ifdef CONFIG_RFS_ACCEL
/* Order of these is important, since filter_id >= %EFX_ARFS_FILTER_ID_PENDING
* is used to test if filter does or will exist.
*/
#define EFX_ARFS_FILTER_ID_PENDING -1
#define EFX_ARFS_FILTER_ID_ERROR -2
#define EFX_ARFS_FILTER_ID_REMOVING -3
/**
* struct efx_arfs_rule - record of an ARFS filter and its IDs
* @node: linkage into hash table
* @spec: details of the filter (used as key for hash table). Use efx->type to
* determine which member to use.
* @rxq_index: channel to which the filter will steer traffic.
* @arfs_id: filter ID which was returned to ARFS
* @filter_id: index in software filter table. May be
* %EFX_ARFS_FILTER_ID_PENDING if filter was not inserted yet,
* %EFX_ARFS_FILTER_ID_ERROR if filter insertion failed, or
* %EFX_ARFS_FILTER_ID_REMOVING if expiry is currently removing the filter.
*/
struct efx_arfs_rule {
struct hlist_node node;
struct efx_filter_spec spec;
u16 rxq_index;
u16 arfs_id;
s32 filter_id;
};
/* Size chosen so that the table is one page (4kB) */
#define EFX_ARFS_HASH_TABLE_SIZE 512
/**
* struct efx_async_filter_insertion - Request to asynchronously insert a filter
* @net_dev: Reference to the netdevice
@ -873,6 +902,10 @@ struct efx_async_filter_insertion {
* @rps_expire_channel's @rps_flow_id
* @rps_slot_map: bitmap of in-flight entries in @rps_slot
* @rps_slot: array of ARFS insertion requests for efx_filter_rfs_work()
* @rps_hash_lock: Protects ARFS filter mapping state (@rps_hash_table and
* @rps_next_id).
* @rps_hash_table: Mapping between ARFS filters and their various IDs
* @rps_next_id: next arfs_id for an ARFS filter
* @active_queues: Count of RX and TX queues that haven't been flushed and drained.
* @rxq_flush_pending: Count of number of receive queues that need to be flushed.
* Decremented when the efx_flush_rx_queue() is called.
@ -1029,6 +1062,9 @@ struct efx_nic {
unsigned int rps_expire_index;
unsigned long rps_slot_map;
struct efx_async_filter_insertion rps_slot[EFX_RPS_MAX_IN_FLIGHT];
spinlock_t rps_hash_lock;
struct hlist_head *rps_hash_table;
u32 rps_next_id;
#endif
atomic_t active_queues;

View File

@ -834,9 +834,29 @@ static void efx_filter_rfs_work(struct work_struct *data)
struct efx_nic *efx = netdev_priv(req->net_dev);
struct efx_channel *channel = efx_get_channel(efx, req->rxq_index);
int slot_idx = req - efx->rps_slot;
struct efx_arfs_rule *rule;
u16 arfs_id = 0;
int rc;
rc = efx->type->filter_insert(efx, &req->spec, true);
if (efx->rps_hash_table) {
spin_lock_bh(&efx->rps_hash_lock);
rule = efx_rps_hash_find(efx, &req->spec);
/* The rule might have already gone, if someone else's request
* for the same spec was already worked and then expired before
* we got around to our work. In that case we have nothing
* tying us to an arfs_id, meaning that as soon as the filter
* is considered for expiry it will be removed.
*/
if (rule) {
if (rc < 0)
rule->filter_id = EFX_ARFS_FILTER_ID_ERROR;
else
rule->filter_id = rc;
arfs_id = rule->arfs_id;
}
spin_unlock_bh(&efx->rps_hash_lock);
}
if (rc >= 0) {
/* Remember this so we can check whether to expire the filter
* later.
@ -848,18 +868,18 @@ static void efx_filter_rfs_work(struct work_struct *data)
if (req->spec.ether_type == htons(ETH_P_IP))
netif_info(efx, rx_status, efx->net_dev,
"steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
"steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d id %u]\n",
(req->spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
req->spec.rem_host, ntohs(req->spec.rem_port),
req->spec.loc_host, ntohs(req->spec.loc_port),
req->rxq_index, req->flow_id, rc);
req->rxq_index, req->flow_id, rc, arfs_id);
else
netif_info(efx, rx_status, efx->net_dev,
"steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n",
"steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d id %u]\n",
(req->spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
req->spec.rem_host, ntohs(req->spec.rem_port),
req->spec.loc_host, ntohs(req->spec.loc_port),
req->rxq_index, req->flow_id, rc);
req->rxq_index, req->flow_id, rc, arfs_id);
}
/* Release references */
@ -872,8 +892,10 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_async_filter_insertion *req;
struct efx_arfs_rule *rule;
struct flow_keys fk;
int slot_idx;
bool new;
int rc;
/* find a free slot */
@ -926,12 +948,42 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
req->spec.rem_port = fk.ports.src;
req->spec.loc_port = fk.ports.dst;
if (efx->rps_hash_table) {
/* Add it to ARFS hash table */
spin_lock(&efx->rps_hash_lock);
rule = efx_rps_hash_add(efx, &req->spec, &new);
if (!rule) {
rc = -ENOMEM;
goto out_unlock;
}
if (new)
rule->arfs_id = efx->rps_next_id++ % RPS_NO_FILTER;
rc = rule->arfs_id;
/* Skip if existing or pending filter already does the right thing */
if (!new && rule->rxq_index == rxq_index &&
rule->filter_id >= EFX_ARFS_FILTER_ID_PENDING)
goto out_unlock;
rule->rxq_index = rxq_index;
rule->filter_id = EFX_ARFS_FILTER_ID_PENDING;
spin_unlock(&efx->rps_hash_lock);
} else {
/* Without an ARFS hash table, we just use arfs_id 0 for all
* filters. This means if multiple flows hash to the same
* flow_id, all but the most recently touched will be eligible
* for expiry.
*/
rc = 0;
}
/* Queue the request */
dev_hold(req->net_dev = net_dev);
INIT_WORK(&req->work, efx_filter_rfs_work);
req->rxq_index = rxq_index;
req->flow_id = flow_id;
schedule_work(&req->work);
return 0;
return rc;
out_unlock:
spin_unlock(&efx->rps_hash_lock);
out_clear:
clear_bit(slot_idx, &efx->rps_slot_map);
return rc;

View File

@ -129,7 +129,7 @@ do { \
#define RX_PRIORITY_MAPPING 0x76543210
#define TX_PRIORITY_MAPPING 0x33221100
#define CPDMA_TX_PRIORITY_MAP 0x01234567
#define CPDMA_TX_PRIORITY_MAP 0x76543210
#define CPSW_VLAN_AWARE BIT(1)
#define CPSW_RX_VLAN_ENCAP BIT(2)

View File

@ -1393,6 +1393,15 @@ static int m88e1318_set_wol(struct phy_device *phydev,
if (err < 0)
goto error;
/* If WOL event happened once, the LED[2] interrupt pin
* will not be cleared unless we reading the interrupt status
* register. If interrupts are in use, the normal interrupt
* handling will clear the WOL event. Clear the WOL event
* before enabling it if !phy_interrupt_is_valid()
*/
if (!phy_interrupt_is_valid(phydev))
phy_read(phydev, MII_M1011_IEVENT);
/* Enable the WOL interrupt */
err = __phy_modify(phydev, MII_88E1318S_PHY_CSIER, 0,
MII_88E1318S_PHY_CSIER_WOL_EIE);

View File

@ -620,6 +620,10 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
lock_sock(sk);
error = -EINVAL;
if (sockaddr_len != sizeof(struct sockaddr_pppox))
goto end;
if (sp->sa_protocol != PX_PROTO_OE)
goto end;

View File

@ -1072,14 +1072,11 @@ static void team_port_leave(struct team *team, struct team_port *port)
}
#ifdef CONFIG_NET_POLL_CONTROLLER
static int team_port_enable_netpoll(struct team *team, struct team_port *port)
static int __team_port_enable_netpoll(struct team_port *port)
{
struct netpoll *np;
int err;
if (!team->dev->npinfo)
return 0;
np = kzalloc(sizeof(*np), GFP_KERNEL);
if (!np)
return -ENOMEM;
@ -1093,6 +1090,14 @@ static int team_port_enable_netpoll(struct team *team, struct team_port *port)
return err;
}
static int team_port_enable_netpoll(struct team_port *port)
{
if (!port->team->dev->npinfo)
return 0;
return __team_port_enable_netpoll(port);
}
static void team_port_disable_netpoll(struct team_port *port)
{
struct netpoll *np = port->np;
@ -1107,7 +1112,7 @@ static void team_port_disable_netpoll(struct team_port *port)
kfree(np);
}
#else
static int team_port_enable_netpoll(struct team *team, struct team_port *port)
static int team_port_enable_netpoll(struct team_port *port)
{
return 0;
}
@ -1221,7 +1226,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
goto err_vids_add;
}
err = team_port_enable_netpoll(team, port);
err = team_port_enable_netpoll(port);
if (err) {
netdev_err(dev, "Failed to enable netpoll on device %s\n",
portname);
@ -1918,7 +1923,7 @@ static int team_netpoll_setup(struct net_device *dev,
mutex_lock(&team->lock);
list_for_each_entry(port, &team->port_list, list) {
err = team_port_enable_netpoll(team, port);
err = __team_port_enable_netpoll(port);
if (err) {
__team_netpoll_cleanup(team);
break;

View File

@ -103,8 +103,7 @@ config NVDIMM_DAX
Select Y if unsure
config OF_PMEM
# FIXME: make tristate once OF_NUMA dependency removed
bool "Device-tree support for persistent memory regions"
tristate "Device-tree support for persistent memory regions"
depends on OF
default LIBNVDIMM
help

View File

@ -88,9 +88,9 @@ int nvdimm_init_nsarea(struct nvdimm_drvdata *ndd)
int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
{
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
int rc = validate_dimm(ndd), cmd_rc = 0;
struct nd_cmd_get_config_data_hdr *cmd;
struct nvdimm_bus_descriptor *nd_desc;
int rc = validate_dimm(ndd);
u32 max_cmd_size, config_size;
size_t offset;
@ -124,9 +124,11 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
cmd->in_offset = offset;
rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
ND_CMD_GET_CONFIG_DATA, cmd,
cmd->in_length + sizeof(*cmd), NULL);
if (rc || cmd->status) {
rc = -ENXIO;
cmd->in_length + sizeof(*cmd), &cmd_rc);
if (rc < 0)
break;
if (cmd_rc < 0) {
rc = cmd_rc;
break;
}
memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length);
@ -140,9 +142,9 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
void *buf, size_t len)
{
int rc = validate_dimm(ndd);
size_t max_cmd_size, buf_offset;
struct nd_cmd_set_config_hdr *cmd;
int rc = validate_dimm(ndd), cmd_rc = 0;
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
@ -164,7 +166,6 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
for (buf_offset = 0; len; len -= cmd->in_length,
buf_offset += cmd->in_length) {
size_t cmd_size;
u32 *status;
cmd->in_offset = offset + buf_offset;
cmd->in_length = min(max_cmd_size, len);
@ -172,12 +173,13 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
/* status is output in the last 4-bytes of the command buffer */
cmd_size = sizeof(*cmd) + cmd->in_length + sizeof(u32);
status = ((void *) cmd) + cmd_size - sizeof(u32);
rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
ND_CMD_SET_CONFIG_DATA, cmd, cmd_size, NULL);
if (rc || *status) {
rc = rc ? rc : -ENXIO;
ND_CMD_SET_CONFIG_DATA, cmd, cmd_size, &cmd_rc);
if (rc < 0)
break;
if (cmd_rc < 0) {
rc = cmd_rc;
break;
}
}

View File

@ -67,7 +67,7 @@ static int of_pmem_region_probe(struct platform_device *pdev)
*/
memset(&ndr_desc, 0, sizeof(ndr_desc));
ndr_desc.attr_groups = region_attr_groups;
ndr_desc.numa_node = of_node_to_nid(np);
ndr_desc.numa_node = dev_to_node(&pdev->dev);
ndr_desc.res = &pdev->resource[i];
ndr_desc.of_node = np;
set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);

View File

@ -740,10 +740,7 @@ static int do_dma_request(struct mport_dma_req *req,
tx->callback = dma_xfer_callback;
tx->callback_param = req;
req->dmach = chan;
req->sync = sync;
req->status = DMA_IN_PROGRESS;
init_completion(&req->req_comp);
kref_get(&req->refcount);
cookie = dmaengine_submit(tx);
@ -831,13 +828,20 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
if (!req)
return -ENOMEM;
kref_init(&req->refcount);
ret = get_dma_channel(priv);
if (ret) {
kfree(req);
return ret;
}
chan = priv->dmach;
kref_init(&req->refcount);
init_completion(&req->req_comp);
req->dir = dir;
req->filp = filp;
req->priv = priv;
req->dmach = chan;
req->sync = sync;
/*
* If parameter loc_addr != NULL, we are transferring data from/to
@ -925,11 +929,6 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
xfer->offset, xfer->length);
}
req->dir = dir;
req->filp = filp;
req->priv = priv;
chan = priv->dmach;
nents = dma_map_sg(chan->device->dev,
req->sgt.sgl, req->sgt.nents, dir);
if (nents == 0) {

View File

@ -557,7 +557,6 @@ enum qeth_prot_versions {
enum qeth_cmd_buffer_state {
BUF_STATE_FREE,
BUF_STATE_LOCKED,
BUF_STATE_PROCESSED,
};
enum qeth_cq {
@ -601,7 +600,6 @@ struct qeth_channel {
struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
atomic_t irq_pending;
int io_buf_no;
int buf_no;
};
/**

View File

@ -706,7 +706,6 @@ void qeth_clear_ipacmd_list(struct qeth_card *card)
qeth_put_reply(reply);
}
spin_unlock_irqrestore(&card->lock, flags);
atomic_set(&card->write.irq_pending, 0);
}
EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
@ -818,7 +817,6 @@ void qeth_clear_cmd_buffers(struct qeth_channel *channel)
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
qeth_release_buffer(channel, &channel->iob[cnt]);
channel->buf_no = 0;
channel->io_buf_no = 0;
}
EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
@ -924,7 +922,6 @@ static int qeth_setup_channel(struct qeth_channel *channel)
kfree(channel->iob[cnt].data);
return -ENOMEM;
}
channel->buf_no = 0;
channel->io_buf_no = 0;
atomic_set(&channel->irq_pending, 0);
spin_lock_init(&channel->iob_lock);
@ -1100,16 +1097,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
{
int rc;
int cstat, dstat;
struct qeth_cmd_buffer *buffer;
struct qeth_cmd_buffer *iob = NULL;
struct qeth_channel *channel;
struct qeth_card *card;
struct qeth_cmd_buffer *iob;
__u8 index;
if (__qeth_check_irb_error(cdev, intparm, irb))
return;
cstat = irb->scsw.cmd.cstat;
dstat = irb->scsw.cmd.dstat;
card = CARD_FROM_CDEV(cdev);
if (!card)
@ -1127,6 +1117,19 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
channel = &card->data;
QETH_CARD_TEXT(card, 5, "data");
}
if (qeth_intparm_is_iob(intparm))
iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
if (__qeth_check_irb_error(cdev, intparm, irb)) {
/* IO was terminated, free its resources. */
if (iob)
qeth_release_buffer(iob->channel, iob);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
return;
}
atomic_set(&channel->irq_pending, 0);
if (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC))
@ -1150,6 +1153,10 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
/* we don't have to handle this further */
intparm = 0;
}
cstat = irb->scsw.cmd.cstat;
dstat = irb->scsw.cmd.dstat;
if ((dstat & DEV_STAT_UNIT_EXCEP) ||
(dstat & DEV_STAT_UNIT_CHECK) ||
(cstat)) {
@ -1182,25 +1189,15 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
channel->state = CH_STATE_RCD_DONE;
goto out;
}
if (intparm) {
buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
buffer->state = BUF_STATE_PROCESSED;
}
if (channel == &card->data)
return;
if (channel == &card->read &&
channel->state == CH_STATE_UP)
__qeth_issue_next_read(card);
iob = channel->iob;
index = channel->buf_no;
while (iob[index].state == BUF_STATE_PROCESSED) {
if (iob[index].callback != NULL)
iob[index].callback(channel, iob + index);
if (iob && iob->callback)
iob->callback(iob->channel, iob);
index = (index + 1) % QETH_CMD_BUFFER_NO;
}
channel->buf_no = index;
out:
wake_up(&card->wait_q);
return;
@ -1870,8 +1867,8 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev,
&channel->ccw, (addr_t) iob, 0, 0);
rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
(addr_t) iob, 0, 0, QETH_TIMEOUT);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) {
@ -1888,7 +1885,6 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
if (channel->state != CH_STATE_UP) {
rc = -ETIME;
QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
qeth_clear_cmd_buffers(channel);
} else
rc = 0;
return rc;
@ -1942,8 +1938,8 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel,
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev,
&channel->ccw, (addr_t) iob, 0, 0);
rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
(addr_t) iob, 0, 0, QETH_TIMEOUT);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) {
@ -1964,7 +1960,6 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel,
QETH_DBF_MESSAGE(2, "%s IDX activate timed out\n",
dev_name(&channel->ccwdev->dev));
QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME);
qeth_clear_cmd_buffers(channel);
return -ETIME;
}
return qeth_idx_activate_get_answer(channel, idx_reply_cb);
@ -2166,8 +2161,8 @@ int qeth_send_control_data(struct qeth_card *card, int len,
QETH_CARD_TEXT(card, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
(addr_t) iob, 0, 0);
rc = ccw_device_start_timeout(CARD_WDEV(card), &card->write.ccw,
(addr_t) iob, 0, 0, event_timeout);
spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
if (rc) {
QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: "
@ -2199,8 +2194,6 @@ int qeth_send_control_data(struct qeth_card *card, int len,
}
}
if (reply->rc == -EIO)
goto error;
rc = reply->rc;
qeth_put_reply(reply);
return rc;
@ -2211,10 +2204,6 @@ time_err:
list_del_init(&reply->list);
spin_unlock_irqrestore(&reply->card->lock, flags);
atomic_inc(&reply->received);
error:
atomic_set(&card->write.irq_pending, 0);
qeth_release_buffer(iob->channel, iob);
card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO;
rc = reply->rc;
qeth_put_reply(reply);
return rc;
@ -3033,28 +3022,23 @@ static int qeth_send_startlan(struct qeth_card *card)
return rc;
}
static int qeth_default_setadapterparms_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
static int qeth_setadpparms_inspect_rc(struct qeth_ipa_cmd *cmd)
{
struct qeth_ipa_cmd *cmd;
QETH_CARD_TEXT(card, 4, "defadpcb");
cmd = (struct qeth_ipa_cmd *) data;
if (cmd->hdr.return_code == 0)
if (!cmd->hdr.return_code)
cmd->hdr.return_code =
cmd->data.setadapterparms.hdr.return_code;
return 0;
return cmd->hdr.return_code;
}
static int qeth_query_setadapterparms_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
QETH_CARD_TEXT(card, 3, "quyadpcb");
if (qeth_setadpparms_inspect_rc(cmd))
return 0;
cmd = (struct qeth_ipa_cmd *) data;
if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) {
card->info.link_type =
cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
@ -3062,7 +3046,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
}
card->options.adp.supported_funcs =
cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
return 0;
}
static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
@ -3154,22 +3138,20 @@ EXPORT_SYMBOL_GPL(qeth_query_ipassists);
static int qeth_query_switch_attributes_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_switch_info *sw_info;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
struct qeth_query_switch_attributes *attrs;
struct qeth_switch_info *sw_info;
QETH_CARD_TEXT(card, 2, "qswiatcb");
cmd = (struct qeth_ipa_cmd *) data;
sw_info = (struct qeth_switch_info *)reply->param;
if (cmd->data.setadapterparms.hdr.return_code == 0) {
attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
sw_info->capabilities = attrs->capabilities;
sw_info->settings = attrs->settings;
QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities,
sw_info->settings);
}
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
if (qeth_setadpparms_inspect_rc(cmd))
return 0;
sw_info = (struct qeth_switch_info *)reply->param;
attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
sw_info->capabilities = attrs->capabilities;
sw_info->settings = attrs->settings;
QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities,
sw_info->settings);
return 0;
}
@ -4207,16 +4189,13 @@ EXPORT_SYMBOL_GPL(qeth_do_send_packet);
static int qeth_setadp_promisc_mode_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
struct qeth_ipacmd_setadpparms *setparms;
QETH_CARD_TEXT(card, 4, "prmadpcb");
cmd = (struct qeth_ipa_cmd *) data;
setparms = &(cmd->data.setadapterparms);
qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
if (cmd->hdr.return_code) {
if (qeth_setadpparms_inspect_rc(cmd)) {
QETH_CARD_TEXT_(card, 4, "prmrc%x", cmd->hdr.return_code);
setparms->data.mode = SET_PROMISC_MODE_OFF;
}
@ -4286,18 +4265,18 @@ EXPORT_SYMBOL_GPL(qeth_get_stats);
static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
QETH_CARD_TEXT(card, 4, "chgmaccb");
if (qeth_setadpparms_inspect_rc(cmd))
return 0;
cmd = (struct qeth_ipa_cmd *) data;
if (!card->options.layer2 ||
!(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
ether_addr_copy(card->dev->dev_addr,
cmd->data.setadapterparms.data.change_addr.addr);
card->info.mac_bits |= QETH_LAYER2_MAC_READ;
}
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
return 0;
}
@ -4328,13 +4307,15 @@ EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr);
static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
struct qeth_set_access_ctrl *access_ctrl_req;
int fallback = *(int *)reply->param;
QETH_CARD_TEXT(card, 4, "setaccb");
if (cmd->hdr.return_code)
return 0;
qeth_setadpparms_inspect_rc(cmd);
cmd = (struct qeth_ipa_cmd *) data;
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
QETH_DBF_TEXT_(SETUP, 2, "setaccb");
QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name);
@ -4407,7 +4388,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
card->options.isolation = card->options.prev_isolation;
break;
}
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
return 0;
}
@ -4695,14 +4675,15 @@ out:
static int qeth_setadpparms_query_oat_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
struct qeth_qoat_priv *priv;
char *resdata;
int resdatalen;
QETH_CARD_TEXT(card, 3, "qoatcb");
if (qeth_setadpparms_inspect_rc(cmd))
return 0;
cmd = (struct qeth_ipa_cmd *)data;
priv = (struct qeth_qoat_priv *)reply->param;
resdatalen = cmd->data.setadapterparms.hdr.cmdlength;
resdata = (char *)data + 28;
@ -4796,21 +4777,18 @@ out:
static int qeth_query_card_info_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct carrier_info *carrier_info = (struct carrier_info *)reply->param;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
struct qeth_query_card_info *card_info;
struct carrier_info *carrier_info;
QETH_CARD_TEXT(card, 2, "qcrdincb");
carrier_info = (struct carrier_info *)reply->param;
cmd = (struct qeth_ipa_cmd *)data;
card_info = &cmd->data.setadapterparms.data.card_info;
if (cmd->data.setadapterparms.hdr.return_code == 0) {
carrier_info->card_type = card_info->card_type;
carrier_info->port_mode = card_info->port_mode;
carrier_info->port_speed = card_info->port_speed;
}
if (qeth_setadpparms_inspect_rc(cmd))
return 0;
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
card_info = &cmd->data.setadapterparms.data.card_info;
carrier_info->card_type = card_info->card_type;
carrier_info->port_mode = card_info->port_mode;
carrier_info->port_speed = card_info->port_speed;
return 0;
}
@ -4857,7 +4835,7 @@ int qeth_vm_request_mac(struct qeth_card *card)
goto out;
}
ccw_device_get_id(CARD_DDEV(card), &id);
ccw_device_get_id(CARD_RDEV(card), &id);
request->resp_buf_len = sizeof(*response);
request->resp_version = DIAG26C_VERSION2;
request->op_code = DIAG26C_GET_MAC;
@ -6563,10 +6541,14 @@ static int __init qeth_core_init(void)
mutex_init(&qeth_mod_mutex);
qeth_wq = create_singlethread_workqueue("qeth_wq");
if (!qeth_wq) {
rc = -ENOMEM;
goto out_err;
}
rc = qeth_register_dbf_views();
if (rc)
goto out_err;
goto dbf_err;
qeth_core_root_dev = root_device_register("qeth");
rc = PTR_ERR_OR_ZERO(qeth_core_root_dev);
if (rc)
@ -6603,6 +6585,8 @@ slab_err:
root_device_unregister(qeth_core_root_dev);
register_err:
qeth_unregister_dbf_views();
dbf_err:
destroy_workqueue(qeth_wq);
out_err:
pr_err("Initializing the qeth device driver failed\n");
return rc;

View File

@ -35,6 +35,18 @@ extern unsigned char IPA_PDU_HEADER[];
#define QETH_HALT_CHANNEL_PARM -11
#define QETH_RCD_PARM -12
static inline bool qeth_intparm_is_iob(unsigned long intparm)
{
switch (intparm) {
case QETH_CLEAR_CHANNEL_PARM:
case QETH_HALT_CHANNEL_PARM:
case QETH_RCD_PARM:
case 0:
return false;
}
return true;
}
/*****************************************************************************/
/* IP Assist related definitions */
/*****************************************************************************/

View File

@ -121,13 +121,10 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
QETH_CARD_TEXT(card, 2, "L2Setmac");
rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
if (rc == 0) {
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
ether_addr_copy(card->dev->dev_addr, mac);
dev_info(&card->gdev->dev,
"MAC address %pM successfully registered on device %s\n",
card->dev->dev_addr, card->dev->name);
"MAC address %pM successfully registered on device %s\n",
mac, card->dev->name);
} else {
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
switch (rc) {
case -EEXIST:
dev_warn(&card->gdev->dev,
@ -142,19 +139,6 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
return rc;
}
static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
{
int rc;
QETH_CARD_TEXT(card, 2, "L2Delmac");
if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
return 0;
rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC);
if (rc == 0)
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
return rc;
}
static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)
{
enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ?
@ -519,6 +503,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
struct qeth_card *card = dev->ml_priv;
u8 old_addr[ETH_ALEN];
int rc = 0;
QETH_CARD_TEXT(card, 3, "setmac");
@ -530,14 +515,35 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
return -EOPNOTSUPP;
}
QETH_CARD_HEX(card, 3, addr->sa_data, ETH_ALEN);
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
QETH_CARD_TEXT(card, 3, "setmcREC");
return -ERESTARTSYS;
}
rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
if (!rc || (rc == -ENOENT))
rc = qeth_l2_send_setmac(card, addr->sa_data);
return rc ? -EINVAL : 0;
if (!qeth_card_hw_is_reachable(card)) {
ether_addr_copy(dev->dev_addr, addr->sa_data);
return 0;
}
/* don't register the same address twice */
if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
return 0;
/* add the new address, switch over, drop the old */
rc = qeth_l2_send_setmac(card, addr->sa_data);
if (rc)
return rc;
ether_addr_copy(old_addr, dev->dev_addr);
ether_addr_copy(dev->dev_addr, addr->sa_data);
if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
qeth_l2_remove_mac(card, old_addr);
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
return 0;
}
static void qeth_promisc_to_bridge(struct qeth_card *card)
@ -1067,8 +1073,9 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
goto out_remove;
}
if (card->info.type != QETH_CARD_TYPE_OSN)
qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
if (card->info.type != QETH_CARD_TYPE_OSN &&
!qeth_l2_send_setmac(card, card->dev->dev_addr))
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
if (card->info.hwtrap &&
@ -1338,8 +1345,8 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
qeth_prepare_control_data(card, len, iob);
QETH_CARD_TEXT(card, 6, "osnoirqp");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
(addr_t) iob, 0, 0);
rc = ccw_device_start_timeout(CARD_WDEV(card), &card->write.ccw,
(addr_t) iob, 0, 0, QETH_IPA_TIMEOUT);
spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
if (rc) {
QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "

View File

@ -55,6 +55,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
#define WDT_CTRL_WDT_INTR BIT(2)
#define WDT_CTRL_RESET_SYSTEM BIT(1)
#define WDT_CTRL_ENABLE BIT(0)
#define WDT_TIMEOUT_STATUS 0x10
#define WDT_TIMEOUT_STATUS_BOOT_SECONDARY BIT(1)
/*
* WDT_RESET_WIDTH controls the characteristics of the external pulse (if
@ -192,6 +194,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
struct device_node *np;
const char *reset_type;
u32 duration;
u32 status;
int ret;
wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
@ -307,6 +310,10 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
writel(duration - 1, wdt->base + WDT_RESET_WIDTH);
}
status = readl(wdt->base + WDT_TIMEOUT_STATUS);
if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY)
wdt->wdd.bootstatus = WDIOF_CARDRESET;
ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
if (ret) {
dev_err(&pdev->dev, "failed to register\n");

View File

@ -121,7 +121,8 @@ static int rwdt_restart(struct watchdog_device *wdev, unsigned long action,
}
static const struct watchdog_info rwdt_ident = {
.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
WDIOF_CARDRESET,
.identity = "Renesas WDT Watchdog",
};
@ -197,9 +198,10 @@ static int rwdt_probe(struct platform_device *pdev)
return PTR_ERR(clk);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
priv->clk_rate = clk_get_rate(clk);
priv->wdev.bootstatus = (readb_relaxed(priv->base + RWTCSRA) &
RWTCSRA_WOVF) ? WDIOF_CARDRESET : 0;
pm_runtime_put(&pdev->dev);
if (!priv->clk_rate) {

View File

@ -299,7 +299,7 @@ static long sch311x_wdt_ioctl(struct file *file, unsigned int cmd,
if (sch311x_wdt_set_heartbeat(new_timeout))
return -EINVAL;
sch311x_wdt_keepalive();
/* Fall */
/* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);
default:

View File

@ -427,7 +427,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EINVAL;
wdt_keepalive();
/* Fall */
/* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(timeout, uarg.i);

View File

@ -178,7 +178,7 @@ static long wafwdt_ioctl(struct file *file, unsigned int cmd,
timeout = new_timeout;
wafwdt_stop();
wafwdt_start();
/* Fall */
/* Fall through */
case WDIOC_GETTIMEOUT:
return put_user(timeout, p);

View File

@ -749,7 +749,7 @@ static int autofs4_dir_mkdir(struct inode *dir,
autofs4_del_active(dentry);
inode = autofs4_get_inode(dir->i_sb, S_IFDIR | 0555);
inode = autofs4_get_inode(dir->i_sb, S_IFDIR | mode);
if (!inode)
return -ENOMEM;
d_add(dentry, inode);

View File

@ -377,10 +377,10 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
} else
map_addr = vm_mmap(filep, addr, size, prot, type, off);
if ((type & MAP_FIXED_NOREPLACE) && BAD_ADDR(map_addr))
pr_info("%d (%s): Uhuuh, elf segment at %p requested but the memory is mapped already\n",
task_pid_nr(current), current->comm,
(void *)addr);
if ((type & MAP_FIXED_NOREPLACE) &&
PTR_ERR((void *)map_addr) == -EEXIST)
pr_info("%d (%s): Uhuuh, elf segment at %px requested but the memory is mapped already\n",
task_pid_nr(current), current->comm, (void *)addr);
return(map_addr);
}

View File

@ -459,6 +459,25 @@ struct btrfs_block_rsv {
unsigned short full;
unsigned short type;
unsigned short failfast;
/*
* Qgroup equivalent for @size @reserved
*
* Unlike normal @size/@reserved for inode rsv, qgroup doesn't care
* about things like csum size nor how many tree blocks it will need to
* reserve.
*
* Qgroup cares more about net change of the extent usage.
*
* So for one newly inserted file extent, in worst case it will cause
* leaf split and level increase, nodesize for each file extent is
* already too much.
*
* In short, qgroup_size/reserved is the upper limit of possible needed
* qgroup metadata reservation.
*/
u64 qgroup_rsv_size;
u64 qgroup_rsv_reserved;
};
/*
@ -714,6 +733,12 @@ struct btrfs_delayed_root;
*/
#define BTRFS_FS_EXCL_OP 16
/*
* To info transaction_kthread we need an immediate commit so it doesn't
* need to wait for commit_interval
*/
#define BTRFS_FS_NEED_ASYNC_COMMIT 17
struct btrfs_fs_info {
u8 fsid[BTRFS_FSID_SIZE];
u8 chunk_tree_uuid[BTRFS_UUID_SIZE];

View File

@ -556,6 +556,12 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
dst_rsv = &fs_info->delayed_block_rsv;
num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1);
/*
* Here we migrate space rsv from transaction rsv, since have already
* reserved space when starting a transaction. So no need to reserve
* qgroup space here.
*/
ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1);
if (!ret) {
trace_btrfs_space_reservation(fs_info, "delayed_item",
@ -577,7 +583,10 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
return;
rsv = &fs_info->delayed_block_rsv;
btrfs_qgroup_convert_reserved_meta(root, item->bytes_reserved);
/*
* Check btrfs_delayed_item_reserve_metadata() to see why we don't need
* to release/reserve qgroup space.
*/
trace_btrfs_space_reservation(fs_info, "delayed_item",
item->key.objectid, item->bytes_reserved,
0);
@ -602,9 +611,6 @@ static int btrfs_delayed_inode_reserve_metadata(
num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1);
ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
if (ret < 0)
return ret;
/*
* btrfs_dirty_inode will update the inode under btrfs_join_transaction
* which doesn't reserve space for speed. This is a problem since we
@ -616,6 +622,10 @@ static int btrfs_delayed_inode_reserve_metadata(
*/
if (!src_rsv || (!trans->bytes_reserved &&
src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) {
ret = btrfs_qgroup_reserve_meta_prealloc(root,
fs_info->nodesize, true);
if (ret < 0)
return ret;
ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes,
BTRFS_RESERVE_NO_FLUSH);
/*
@ -634,6 +644,8 @@ static int btrfs_delayed_inode_reserve_metadata(
"delayed_inode",
btrfs_ino(inode),
num_bytes, 1);
} else {
btrfs_qgroup_free_meta_prealloc(root, fs_info->nodesize);
}
return ret;
}

View File

@ -540,8 +540,10 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_head *head_ref,
struct btrfs_qgroup_extent_record *qrecord,
u64 bytenr, u64 num_bytes, u64 ref_root, u64 reserved,
int action, int is_data, int *qrecord_inserted_ret,
int action, int is_data, int is_system,
int *qrecord_inserted_ret,
int *old_ref_mod, int *new_ref_mod)
{
struct btrfs_delayed_ref_head *existing;
struct btrfs_delayed_ref_root *delayed_refs;
@ -585,6 +587,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
head_ref->ref_mod = count_mod;
head_ref->must_insert_reserved = must_insert_reserved;
head_ref->is_data = is_data;
head_ref->is_system = is_system;
head_ref->ref_tree = RB_ROOT;
INIT_LIST_HEAD(&head_ref->ref_add_list);
RB_CLEAR_NODE(&head_ref->href_node);
@ -772,6 +775,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
struct btrfs_delayed_ref_root *delayed_refs;
struct btrfs_qgroup_extent_record *record = NULL;
int qrecord_inserted;
int is_system = (ref_root == BTRFS_CHUNK_TREE_OBJECTID);
BUG_ON(extent_op && extent_op->is_data);
ref = kmem_cache_alloc(btrfs_delayed_tree_ref_cachep, GFP_NOFS);
@ -800,8 +804,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
*/
head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record,
bytenr, num_bytes, 0, 0, action, 0,
&qrecord_inserted, old_ref_mod,
new_ref_mod);
is_system, &qrecord_inserted,
old_ref_mod, new_ref_mod);
add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr,
num_bytes, parent, ref_root, level, action);
@ -868,7 +872,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
*/
head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record,
bytenr, num_bytes, ref_root, reserved,
action, 1, &qrecord_inserted,
action, 1, 0, &qrecord_inserted,
old_ref_mod, new_ref_mod);
add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr,
@ -898,9 +902,14 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
delayed_refs = &trans->transaction->delayed_refs;
spin_lock(&delayed_refs->lock);
/*
* extent_ops just modify the flags of an extent and they don't result
* in ref count changes, hence it's safe to pass false/0 for is_system
* argument
*/
add_delayed_ref_head(fs_info, trans, head_ref, NULL, bytenr,
num_bytes, 0, 0, BTRFS_UPDATE_DELAYED_HEAD,
extent_op->is_data, NULL, NULL, NULL);
extent_op->is_data, 0, NULL, NULL, NULL);
spin_unlock(&delayed_refs->lock);
return 0;

View File

@ -127,6 +127,7 @@ struct btrfs_delayed_ref_head {
*/
unsigned int must_insert_reserved:1;
unsigned int is_data:1;
unsigned int is_system:1;
unsigned int processing:1;
};

View File

@ -1824,6 +1824,7 @@ static int transaction_kthread(void *arg)
now = get_seconds();
if (cur->state < TRANS_STATE_BLOCKED &&
!test_bit(BTRFS_FS_NEED_ASYNC_COMMIT, &fs_info->flags) &&
(now < cur->start_time ||
now - cur->start_time < fs_info->commit_interval)) {
spin_unlock(&fs_info->trans_lock);

View File

@ -2601,13 +2601,19 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
trace_run_delayed_ref_head(fs_info, head, 0);
if (head->total_ref_mod < 0) {
struct btrfs_block_group_cache *cache;
struct btrfs_space_info *space_info;
u64 flags;
cache = btrfs_lookup_block_group(fs_info, head->bytenr);
ASSERT(cache);
percpu_counter_add(&cache->space_info->total_bytes_pinned,
if (head->is_data)
flags = BTRFS_BLOCK_GROUP_DATA;
else if (head->is_system)
flags = BTRFS_BLOCK_GROUP_SYSTEM;
else
flags = BTRFS_BLOCK_GROUP_METADATA;
space_info = __find_space_info(fs_info, flags);
ASSERT(space_info);
percpu_counter_add(&space_info->total_bytes_pinned,
-head->num_bytes);
btrfs_put_block_group(cache);
if (head->is_data) {
spin_lock(&delayed_refs->lock);
@ -5559,14 +5565,18 @@ again:
static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
struct btrfs_block_rsv *block_rsv,
struct btrfs_block_rsv *dest, u64 num_bytes)
struct btrfs_block_rsv *dest, u64 num_bytes,
u64 *qgroup_to_release_ret)
{
struct btrfs_space_info *space_info = block_rsv->space_info;
u64 qgroup_to_release = 0;
u64 ret;
spin_lock(&block_rsv->lock);
if (num_bytes == (u64)-1)
if (num_bytes == (u64)-1) {
num_bytes = block_rsv->size;
qgroup_to_release = block_rsv->qgroup_rsv_size;
}
block_rsv->size -= num_bytes;
if (block_rsv->reserved >= block_rsv->size) {
num_bytes = block_rsv->reserved - block_rsv->size;
@ -5575,6 +5585,13 @@ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
} else {
num_bytes = 0;
}
if (block_rsv->qgroup_rsv_reserved >= block_rsv->qgroup_rsv_size) {
qgroup_to_release = block_rsv->qgroup_rsv_reserved -
block_rsv->qgroup_rsv_size;
block_rsv->qgroup_rsv_reserved = block_rsv->qgroup_rsv_size;
} else {
qgroup_to_release = 0;
}
spin_unlock(&block_rsv->lock);
ret = num_bytes;
@ -5597,6 +5614,8 @@ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
space_info_add_old_bytes(fs_info, space_info,
num_bytes);
}
if (qgroup_to_release_ret)
*qgroup_to_release_ret = qgroup_to_release;
return ret;
}
@ -5738,17 +5757,21 @@ static int btrfs_inode_rsv_refill(struct btrfs_inode *inode,
struct btrfs_root *root = inode->root;
struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
u64 num_bytes = 0;
u64 qgroup_num_bytes = 0;
int ret = -ENOSPC;
spin_lock(&block_rsv->lock);
if (block_rsv->reserved < block_rsv->size)
num_bytes = block_rsv->size - block_rsv->reserved;
if (block_rsv->qgroup_rsv_reserved < block_rsv->qgroup_rsv_size)
qgroup_num_bytes = block_rsv->qgroup_rsv_size -
block_rsv->qgroup_rsv_reserved;
spin_unlock(&block_rsv->lock);
if (num_bytes == 0)
return 0;
ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_num_bytes, true);
if (ret)
return ret;
ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
@ -5756,7 +5779,13 @@ static int btrfs_inode_rsv_refill(struct btrfs_inode *inode,
block_rsv_add_bytes(block_rsv, num_bytes, 0);
trace_btrfs_space_reservation(root->fs_info, "delalloc",
btrfs_ino(inode), num_bytes, 1);
}
/* Don't forget to increase qgroup_rsv_reserved */
spin_lock(&block_rsv->lock);
block_rsv->qgroup_rsv_reserved += qgroup_num_bytes;
spin_unlock(&block_rsv->lock);
} else
btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);
return ret;
}
@ -5777,20 +5806,23 @@ static void btrfs_inode_rsv_release(struct btrfs_inode *inode, bool qgroup_free)
struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
u64 released = 0;
u64 qgroup_to_release = 0;
/*
* Since we statically set the block_rsv->size we just want to say we
* are releasing 0 bytes, and then we'll just get the reservation over
* the size free'd.
*/
released = block_rsv_release_bytes(fs_info, block_rsv, global_rsv, 0);
released = block_rsv_release_bytes(fs_info, block_rsv, global_rsv, 0,
&qgroup_to_release);
if (released > 0)
trace_btrfs_space_reservation(fs_info, "delalloc",
btrfs_ino(inode), released, 0);
if (qgroup_free)
btrfs_qgroup_free_meta_prealloc(inode->root, released);
btrfs_qgroup_free_meta_prealloc(inode->root, qgroup_to_release);
else
btrfs_qgroup_convert_reserved_meta(inode->root, released);
btrfs_qgroup_convert_reserved_meta(inode->root,
qgroup_to_release);
}
void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info,
@ -5802,7 +5834,7 @@ void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info,
if (global_rsv == block_rsv ||
block_rsv->space_info != global_rsv->space_info)
global_rsv = NULL;
block_rsv_release_bytes(fs_info, block_rsv, global_rsv, num_bytes);
block_rsv_release_bytes(fs_info, block_rsv, global_rsv, num_bytes, NULL);
}
static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
@ -5882,7 +5914,7 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
{
block_rsv_release_bytes(fs_info, &fs_info->global_block_rsv, NULL,
(u64)-1);
(u64)-1, NULL);
WARN_ON(fs_info->trans_block_rsv.size > 0);
WARN_ON(fs_info->trans_block_rsv.reserved > 0);
WARN_ON(fs_info->chunk_block_rsv.size > 0);
@ -5906,7 +5938,7 @@ void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
WARN_ON_ONCE(!list_empty(&trans->new_bgs));
block_rsv_release_bytes(fs_info, &fs_info->chunk_block_rsv, NULL,
trans->chunk_bytes_reserved);
trans->chunk_bytes_reserved, NULL);
trans->chunk_bytes_reserved = 0;
}
@ -6011,6 +6043,7 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
{
struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
u64 reserve_size = 0;
u64 qgroup_rsv_size = 0;
u64 csum_leaves;
unsigned outstanding_extents;
@ -6023,9 +6056,17 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
inode->csum_bytes);
reserve_size += btrfs_calc_trans_metadata_size(fs_info,
csum_leaves);
/*
* For qgroup rsv, the calculation is very simple:
* account one nodesize for each outstanding extent
*
* This is overestimating in most cases.
*/
qgroup_rsv_size = outstanding_extents * fs_info->nodesize;
spin_lock(&block_rsv->lock);
block_rsv->size = reserve_size;
block_rsv->qgroup_rsv_size = qgroup_rsv_size;
spin_unlock(&block_rsv->lock);
}
@ -8403,7 +8444,7 @@ static void unuse_block_rsv(struct btrfs_fs_info *fs_info,
struct btrfs_block_rsv *block_rsv, u32 blocksize)
{
block_rsv_add_bytes(block_rsv, blocksize, 0);
block_rsv_release_bytes(fs_info, block_rsv, NULL, 0);
block_rsv_release_bytes(fs_info, block_rsv, NULL, 0, NULL);
}
/*

View File

@ -1748,7 +1748,7 @@ again:
unlock_extent_cached(&BTRFS_I(inode)->io_tree,
lockstart, lockend, &cached_state);
btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes,
(ret != 0));
true);
if (ret) {
btrfs_drop_pages(pages, num_pages);
break;

View File

@ -31,6 +31,7 @@
#include <linux/uio.h>
#include <linux/magic.h>
#include <linux/iversion.h>
#include <asm/unaligned.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
@ -5905,11 +5906,13 @@ static int btrfs_filldir(void *addr, int entries, struct dir_context *ctx)
struct dir_entry *entry = addr;
char *name = (char *)(entry + 1);
ctx->pos = entry->offset;
if (!dir_emit(ctx, name, entry->name_len, entry->ino,
entry->type))
ctx->pos = get_unaligned(&entry->offset);
if (!dir_emit(ctx, name, get_unaligned(&entry->name_len),
get_unaligned(&entry->ino),
get_unaligned(&entry->type)))
return 1;
addr += sizeof(struct dir_entry) + entry->name_len;
addr += sizeof(struct dir_entry) +
get_unaligned(&entry->name_len);
ctx->pos++;
}
return 0;
@ -5999,14 +6002,15 @@ again:
}
entry = addr;
entry->name_len = name_len;
put_unaligned(name_len, &entry->name_len);
name_ptr = (char *)(entry + 1);
read_extent_buffer(leaf, name_ptr, (unsigned long)(di + 1),
name_len);
entry->type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
put_unaligned(btrfs_filetype_table[btrfs_dir_type(leaf, di)],
&entry->type);
btrfs_dir_item_key_to_cpu(leaf, di, &location);
entry->ino = location.objectid;
entry->offset = found_key.offset;
put_unaligned(location.objectid, &entry->ino);
put_unaligned(found_key.offset, &entry->offset);
entries++;
addr += sizeof(struct dir_entry) + name_len;
total_len += sizeof(struct dir_entry) + name_len;

View File

@ -189,9 +189,10 @@ void btrfs_print_leaf(struct extent_buffer *l)
fs_info = l->fs_info;
nr = btrfs_header_nritems(l);
btrfs_info(fs_info, "leaf %llu total ptrs %d free space %d",
btrfs_header_bytenr(l), nr,
btrfs_leaf_free_space(fs_info, l));
btrfs_info(fs_info,
"leaf %llu gen %llu total ptrs %d free space %d owner %llu",
btrfs_header_bytenr(l), btrfs_header_generation(l), nr,
btrfs_leaf_free_space(fs_info, l), btrfs_header_owner(l));
for (i = 0 ; i < nr ; i++) {
item = btrfs_item_nr(i);
btrfs_item_key_to_cpu(l, &key, i);
@ -325,7 +326,7 @@ void btrfs_print_leaf(struct extent_buffer *l)
}
}
void btrfs_print_tree(struct extent_buffer *c)
void btrfs_print_tree(struct extent_buffer *c, bool follow)
{
struct btrfs_fs_info *fs_info;
int i; u32 nr;
@ -342,15 +343,19 @@ void btrfs_print_tree(struct extent_buffer *c)
return;
}
btrfs_info(fs_info,
"node %llu level %d total ptrs %d free spc %u",
btrfs_header_bytenr(c), level, nr,
(u32)BTRFS_NODEPTRS_PER_BLOCK(fs_info) - nr);
"node %llu level %d gen %llu total ptrs %d free spc %u owner %llu",
btrfs_header_bytenr(c), level, btrfs_header_generation(c),
nr, (u32)BTRFS_NODEPTRS_PER_BLOCK(fs_info) - nr,
btrfs_header_owner(c));
for (i = 0; i < nr; i++) {
btrfs_node_key_to_cpu(c, &key, i);
pr_info("\tkey %d (%llu %u %llu) block %llu\n",
pr_info("\tkey %d (%llu %u %llu) block %llu gen %llu\n",
i, key.objectid, key.type, key.offset,
btrfs_node_blockptr(c, i));
btrfs_node_blockptr(c, i),
btrfs_node_ptr_generation(c, i));
}
if (!follow)
return;
for (i = 0; i < nr; i++) {
struct btrfs_key first_key;
struct extent_buffer *next;
@ -372,7 +377,7 @@ void btrfs_print_tree(struct extent_buffer *c)
if (btrfs_header_level(next) !=
level - 1)
BUG();
btrfs_print_tree(next);
btrfs_print_tree(next, follow);
free_extent_buffer(next);
}
}

View File

@ -7,6 +7,6 @@
#define BTRFS_PRINT_TREE_H
void btrfs_print_leaf(struct extent_buffer *l);
void btrfs_print_tree(struct extent_buffer *c);
void btrfs_print_tree(struct extent_buffer *c, bool follow);
#endif

View File

@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/btrfs.h>
#include <linux/sizes.h>
#include "ctree.h"
#include "transaction.h"
@ -2375,8 +2376,21 @@ out:
return ret;
}
static bool qgroup_check_limits(const struct btrfs_qgroup *qg, u64 num_bytes)
/*
* Two limits to commit transaction in advance.
*
* For RATIO, it will be 1/RATIO of the remaining limit
* (excluding data and prealloc meta) as threshold.
* For SIZE, it will be in byte unit as threshold.
*/
#define QGROUP_PERTRANS_RATIO 32
#define QGROUP_PERTRANS_SIZE SZ_32M
static bool qgroup_check_limits(struct btrfs_fs_info *fs_info,
const struct btrfs_qgroup *qg, u64 num_bytes)
{
u64 limit;
u64 threshold;
if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
qgroup_rsv_total(qg) + (s64)qg->rfer + num_bytes > qg->max_rfer)
return false;
@ -2385,6 +2399,31 @@ static bool qgroup_check_limits(const struct btrfs_qgroup *qg, u64 num_bytes)
qgroup_rsv_total(qg) + (s64)qg->excl + num_bytes > qg->max_excl)
return false;
/*
* Even if we passed the check, it's better to check if reservation
* for meta_pertrans is pushing us near limit.
* If there is too much pertrans reservation or it's near the limit,
* let's try commit transaction to free some, using transaction_kthread
*/
if ((qg->lim_flags & (BTRFS_QGROUP_LIMIT_MAX_RFER |
BTRFS_QGROUP_LIMIT_MAX_EXCL))) {
if (qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
limit = qg->max_excl;
else
limit = qg->max_rfer;
threshold = (limit - qg->rsv.values[BTRFS_QGROUP_RSV_DATA] -
qg->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC]) /
QGROUP_PERTRANS_RATIO;
threshold = min_t(u64, threshold, QGROUP_PERTRANS_SIZE);
/*
* Use transaction_kthread to commit transaction, so we no
* longer need to bother nested transaction nor lock context.
*/
if (qg->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > threshold)
btrfs_commit_transaction_locksafe(fs_info);
}
return true;
}
@ -2434,7 +2473,7 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce,
qg = unode_aux_to_qgroup(unode);
if (enforce && !qgroup_check_limits(qg, num_bytes)) {
if (enforce && !qgroup_check_limits(fs_info, qg, num_bytes)) {
ret = -EDQUOT;
goto out;
}

View File

@ -2267,6 +2267,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
*/
cur_trans->state = TRANS_STATE_COMPLETED;
wake_up(&cur_trans->commit_wait);
clear_bit(BTRFS_FS_NEED_ASYNC_COMMIT, &fs_info->flags);
spin_lock(&fs_info->trans_lock);
list_del_init(&cur_trans->list);

View File

@ -199,6 +199,20 @@ int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root);
int btrfs_commit_transaction(struct btrfs_trans_handle *trans);
int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
int wait_for_unblock);
/*
* Try to commit transaction asynchronously, so this is safe to call
* even holding a spinlock.
*
* It's done by informing transaction_kthread to commit transaction without
* waiting for commit interval.
*/
static inline void btrfs_commit_transaction_locksafe(
struct btrfs_fs_info *fs_info)
{
set_bit(BTRFS_FS_NEED_ASYNC_COMMIT, &fs_info->flags);
wake_up_process(fs_info->transaction_kthread);
}
int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans);
int btrfs_should_end_transaction(struct btrfs_trans_handle *trans);
void btrfs_throttle(struct btrfs_fs_info *fs_info);

View File

@ -54,7 +54,7 @@ do { \
pr_debug_ ## ratefunc("%s: " \
fmt, __FILE__, ##__VA_ARGS__); \
} else if ((type) & VFS) { \
pr_err_ ## ratefunc("CuIFS VFS: " \
pr_err_ ## ratefunc("CIFS VFS: " \
fmt, ##__VA_ARGS__); \
} else if ((type) & NOISY && (NOISY != 0)) { \
pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \

View File

@ -684,6 +684,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
goto mknod_out;
}
if (!S_ISCHR(mode) && !S_ISBLK(mode))
goto mknod_out;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
goto mknod_out;
@ -692,10 +695,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) {
kfree(full_path);
rc = -ENOMEM;
free_xid(xid);
return rc;
goto mknod_out;
}
if (backup_cred(cifs_sb))
@ -742,7 +743,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
pdev->minor = cpu_to_le64(MINOR(device_number));
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
&bytes_written, iov, 1);
} /* else if (S_ISFIFO) */
}
tcon->ses->server->ops->close(xid, tcon, &fid);
d_drop(direntry);

View File

@ -3462,7 +3462,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
* If the page is mmap'ed into a process' page tables, then we need to make
* sure that it doesn't change while being written back.
*/
static int
static vm_fault_t
cifs_page_mkwrite(struct vm_fault *vmf)
{
struct page *page = vmf->page;

View File

@ -1452,7 +1452,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_open_parms oparms;
struct cifs_fid fid;
struct kvec err_iov = {NULL, 0};
struct smb2_err_rsp *err_buf = NULL;
struct smb2_err_rsp *err_buf;
struct smb2_symlink_err_rsp *symlink;
unsigned int sub_len;
unsigned int sub_offset;
@ -1476,7 +1476,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
if (!rc || !err_buf) {
if (!rc || !err_iov.iov_base) {
kfree(utf16_path);
return -ENOENT;
}

View File

@ -1028,7 +1028,7 @@ static int smbd_post_send(struct smbd_connection *info,
for (i = 0; i < request->num_sge; i++) {
log_rdma_send(INFO,
"rdma_request sge[%d] addr=%llu length=%u\n",
i, request->sge[0].addr, request->sge[0].length);
i, request->sge[i].addr, request->sge[i].length);
ib_dma_sync_single_for_device(
info->id->device,
request->sge[i].addr,
@ -2139,6 +2139,10 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
goto done;
}
cifs_dbg(FYI, "Sending smb (RDMA): smb_len=%u\n", buflen);
for (i = 0; i < rqst->rq_nvec-1; i++)
dump_smb(iov[i].iov_base, iov[i].iov_len);
remaining_data_length = buflen;
log_write(INFO, "rqst->rq_nvec=%d rqst->rq_npages=%d rq_pagesz=%d "
@ -2194,6 +2198,8 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
goto done;
}
i++;
if (i == rqst->rq_nvec)
break;
}
start = i;
buflen = 0;

View File

@ -745,11 +745,12 @@ int inode_congested(struct inode *inode, int cong_bits)
*/
if (inode && inode_to_wb_is_valid(inode)) {
struct bdi_writeback *wb;
bool locked, congested;
struct wb_lock_cookie lock_cookie = {};
bool congested;
wb = unlocked_inode_to_wb_begin(inode, &locked);
wb = unlocked_inode_to_wb_begin(inode, &lock_cookie);
congested = wb_congested(wb, cong_bits);
unlocked_inode_to_wb_end(inode, locked);
unlocked_inode_to_wb_end(inode, &lock_cookie);
return congested;
}

View File

@ -1693,6 +1693,12 @@ void task_dump_owner(struct task_struct *task, umode_t mode,
kuid_t uid;
kgid_t gid;
if (unlikely(task->flags & PF_KTHREAD)) {
*ruid = GLOBAL_ROOT_UID;
*rgid = GLOBAL_ROOT_GID;
return;
}
/* Default to the tasks effective ownership */
rcu_read_lock();
cred = __task_cred(task);

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