Merge 4.9.33 into android-4.9
Changes in 4.9.33 PCI/PM: Add needs_resume flag to avoid suspend complete optimization drm/i915: Prevent the system suspend complete optimization partitions/msdos: FreeBSD UFS2 file systems are not recognized netfilter: nf_conntrack_sip: fix wrong memory initialisation ibmvnic: Fix endian errors in error reporting output ibmvnic: Fix endian error when requesting device capabilities net: xilinx_emaclite: fix freezes due to unordered I/O net: xilinx_emaclite: fix receive buffer overflow tcp: tcp_probe: use spin_lock_bh() ipv6: Handle IPv4-mapped src to in6addr_any dst. ipv6: Inhibit IPv4-mapped src address on the wire. tipc: Fix tipc_sk_reinit race conditions gfs2: Use rhashtable walk interface in glock_hash_walk NET: Fix /proc/net/arp for AX.25 ibmvnic: Call napi_disable instead of napi_enable in failure path ibmvnic: Initialize completion variables before starting work NET: mkiss: Fix panic net: hns: Fix the device being used for dma mapping during TX sierra_net: Skip validating irrelevant fields for IDLE LSIs sierra_net: Add support for IPv6 and Dual-Stack Link Sense Indications i2c: piix4: Request the SMBUS semaphore inside the mutex i2c: piix4: Fix request_region size powerpc/powernv: Properly set "host-ipi" on IPIs kernel/ucount.c: mark user_header with kmemleak_ignore() net: thunderx: Fix PHY autoneg for SGMII QLM mode ipv6: addrconf: fix generation of new temporary addresses vfio/spapr_tce: Set window when adding additional groups to container ipv6: Fix IPv6 packet loss in scenarios involving roaming + snooping switches ARM: defconfigs: make NF_CT_PROTO_SCTP and NF_CT_PROTO_UDPLITE built-in PM / runtime: Avoid false-positive warnings from might_sleep_if() jump label: pass kbuild_cflags when checking for asm goto support shmem: fix sleeping from atomic context kasan: respect /proc/sys/kernel/traceoff_on_warning log2: make order_base_2() behave correctly on const input value zero ethtool: do not vzalloc(0) on registers dump net: phy: Fix lack of reference count on PHY driver net: phy: Fix PHY module checks and NULL deref in phy_attach_direct() net: fix ndo_features_check/ndo_fix_features comment ordering fscache: Fix dead object requeue fscache: Clear outstanding writes when disabling a cookie FS-Cache: Initialise stores_lock in netfs cookie ipv6: fix flow labels when the traffic class is non-0 drm/nouveau: prevent userspace from deleting client object drm/nouveau/fence/g84-: protect against concurrent access to semaphore buffers net/mlx4_core: Avoid command timeouts during VF driver device shutdown gianfar: synchronize DMA API usage by free_skb_rx_queue w/ gfar_new_page pinctrl: baytrail: Rectify debounce support (part 2) cec: fix wrong last_la determination drm: prevent double-(un)registration for connectors drm: Don't race connector registration pinctrl: berlin-bg4ct: fix the value for "sd1a" of pin SCRD0_CRD_PRES net: adaptec: starfire: add checks for dma mapping errors drm/i915: Check for NULL i915_vma in intel_unpin_fb_obj() net/mlx5: E-Switch, Err when retrieving steering name-space fails net/mlx5: Return EOPNOTSUPP when failing to get steering name-space parisc, parport_gsc: Fixes for printk continuation lines net: phy: micrel: add support for KSZ8795 gtp: add genl family modules alias drm/nouveau: Intercept ACPI_VIDEO_NOTIFY_PROBE drm/nouveau: Rename acpi_work to hpd_work drm/nouveau: Handle fbcon suspend/resume in seperate worker drm/nouveau: Don't enabling polling twice on runtime resume drm/nouveau: Fix drm poll_helper handling drm/ast: Fixed system hanged if disable P2A ravb: unmap descriptors when freeing rings nfs: Fix "Don't increment lock sequence ID after NFS4ERR_MOVED" nvmet-rdma: Fix missing dma sync to nvme data structures r8152: avoid start_xmit to call napi_schedule during autosuspend r8152: check rx after napi is enabled r8152: re-schedule napi for tx r8152: fix rtl8152_post_reset function r8152: avoid start_xmit to schedule napi when napi is disabled net-next: ethernet: mediatek: change the compatible string bnxt_en: Fix bnxt_reset() in the slow path task. bnxt_en: Enhance autoneg support. bnxt_en: Fix RTNL lock usage on bnxt_update_link(). bnxt_en: Fix RTNL lock usage on bnxt_get_port_module_status(). sctp: sctp gso should set feature with NETIF_F_SG when calling skb_segment sctp: sctp_addr_id2transport should verify the addr before looking up assoc usb: musb: Fix external abort on non-linefetch for musb_irq_work() mn10300: fix build error of missing fpu_save() romfs: use different way to generate fsid for BLOCK or MTD frv: add atomic64_add_unless() frv: add missing atomic64 operations proc: add a schedule point in proc_pid_readdir() userfaultfd: fix SIGBUS resulting from false rwsem wakeups kernel/watchdog.c: move hardlockup detector to separate file kernel/watchdog.c: move shared definitions to nmi.h kernel/watchdog: prevent false hardlockup on overloaded system vhost/vsock: handle vhost_vq_init_access() error ARC: smp-boot: Decouple Non masters waiting API from jump to entry point ARCv2: smp-boot: wake_flag polling by non-Masters needs to be uncached tipc: ignore requests when the connection state is not CONNECTED tipc: fix connection refcount error tipc: add subscription refcount to avoid invalid delete tipc: fix nametbl_lock soft lockup at node/link events netfilter: nf_tables: fix set->nelems counting with no NLM_F_EXCL netfilter: nft_log: restrict the log prefix length to 127 RDMA/qedr: Dispatch port active event from qedr_add RDMA/qedr: Fix and simplify memory leak in PD alloc RDMA/qedr: Don't reset QP when queues aren't flushed RDMA/qedr: Don't spam dmesg if QP is in error state RDMA/qedr: Return max inline data in QP query result xtensa: don't use linux IRQ #0 s390/kvm: do not rely on the ILC on kvm host protection fauls drm/i915: Workaround VLV/CHV DSI scanline counter hardware fail drm/i915: Always recompute watermarks when distrust_bios_wm is set, v2. sparc64: make string buffers large enough Linux 4.9.33 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 32
|
||||
SUBLEVEL = 33
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
@@ -797,7 +797,7 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types)
|
||||
KBUILD_ARFLAGS := $(call ar-option,D)
|
||||
|
||||
# check for 'asm goto'
|
||||
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
|
||||
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
|
||||
KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
|
||||
KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
|
||||
endif
|
||||
|
||||
@@ -71,14 +71,14 @@ ENTRY(stext)
|
||||
GET_CPU_ID r5
|
||||
cmp r5, 0
|
||||
mov.nz r0, r5
|
||||
#ifdef CONFIG_ARC_SMP_HALT_ON_RESET
|
||||
; Non-Master can proceed as system would be booted sufficiently
|
||||
jnz first_lines_of_secondary
|
||||
#else
|
||||
bz .Lmaster_proceed
|
||||
|
||||
; Non-Masters wait for Master to boot enough and bring them up
|
||||
jnz arc_platform_smp_wait_to_boot
|
||||
#endif
|
||||
; Master falls thru
|
||||
; when they resume, tail-call to entry point
|
||||
mov blink, @first_lines_of_secondary
|
||||
j arc_platform_smp_wait_to_boot
|
||||
|
||||
.Lmaster_proceed:
|
||||
#endif
|
||||
|
||||
; Clear BSS before updating any globals
|
||||
|
||||
+20
-5
@@ -90,22 +90,37 @@ void __init smp_cpus_done(unsigned int max_cpus)
|
||||
*/
|
||||
static volatile int wake_flag;
|
||||
|
||||
#ifdef CONFIG_ISA_ARCOMPACT
|
||||
|
||||
#define __boot_read(f) f
|
||||
#define __boot_write(f, v) f = v
|
||||
|
||||
#else
|
||||
|
||||
#define __boot_read(f) arc_read_uncached_32(&f)
|
||||
#define __boot_write(f, v) arc_write_uncached_32(&f, v)
|
||||
|
||||
#endif
|
||||
|
||||
static void arc_default_smp_cpu_kick(int cpu, unsigned long pc)
|
||||
{
|
||||
BUG_ON(cpu == 0);
|
||||
wake_flag = cpu;
|
||||
|
||||
__boot_write(wake_flag, cpu);
|
||||
}
|
||||
|
||||
void arc_platform_smp_wait_to_boot(int cpu)
|
||||
{
|
||||
while (wake_flag != cpu)
|
||||
/* for halt-on-reset, we've waited already */
|
||||
if (IS_ENABLED(CONFIG_ARC_SMP_HALT_ON_RESET))
|
||||
return;
|
||||
|
||||
while (__boot_read(wake_flag) != cpu)
|
||||
;
|
||||
|
||||
wake_flag = 0;
|
||||
__asm__ __volatile__("j @first_lines_of_secondary \n");
|
||||
__boot_write(wake_flag, 0);
|
||||
}
|
||||
|
||||
|
||||
const char *arc_platform_smp_cpuinfo(void)
|
||||
{
|
||||
return plat_smp_ops.info ? : "";
|
||||
|
||||
@@ -64,8 +64,8 @@ CONFIG_NETFILTER=y
|
||||
CONFIG_NETFILTER_NETLINK_QUEUE=m
|
||||
CONFIG_NF_CONNTRACK=m
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CT_PROTO_SCTP=m
|
||||
CONFIG_NF_CT_PROTO_UDPLITE=m
|
||||
CONFIG_NF_CT_PROTO_SCTP=y
|
||||
CONFIG_NF_CT_PROTO_UDPLITE=y
|
||||
CONFIG_NF_CONNTRACK_AMANDA=m
|
||||
CONFIG_NF_CONNTRACK_FTP=m
|
||||
CONFIG_NF_CONNTRACK_H323=m
|
||||
|
||||
@@ -56,8 +56,8 @@ CONFIG_NETFILTER=y
|
||||
CONFIG_NETFILTER_NETLINK_QUEUE=m
|
||||
CONFIG_NF_CONNTRACK=m
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CT_PROTO_SCTP=m
|
||||
CONFIG_NF_CT_PROTO_UDPLITE=m
|
||||
CONFIG_NF_CT_PROTO_SCTP=y
|
||||
CONFIG_NF_CT_PROTO_UDPLITE=y
|
||||
CONFIG_NF_CONNTRACK_AMANDA=m
|
||||
CONFIG_NF_CONNTRACK_FTP=m
|
||||
CONFIG_NF_CONNTRACK_H323=m
|
||||
|
||||
@@ -139,7 +139,7 @@ static inline void atomic64_dec(atomic64_t *v)
|
||||
#define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0)
|
||||
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
|
||||
#define atomic64_inc_and_test(v) (atomic64_inc_return((v)) == 0)
|
||||
|
||||
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
|
||||
|
||||
#define atomic_cmpxchg(v, old, new) (cmpxchg(&(v)->counter, old, new))
|
||||
#define atomic_xchg(v, new) (xchg(&(v)->counter, new))
|
||||
@@ -161,6 +161,39 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)
|
||||
{
|
||||
long long c, old;
|
||||
|
||||
c = atomic64_read(v);
|
||||
for (;;) {
|
||||
if (unlikely(c == u))
|
||||
break;
|
||||
old = atomic64_cmpxchg(v, c, c + i);
|
||||
if (likely(old == c))
|
||||
break;
|
||||
c = old;
|
||||
}
|
||||
return c != u;
|
||||
}
|
||||
|
||||
static inline long long atomic64_dec_if_positive(atomic64_t *v)
|
||||
{
|
||||
long long c, old, dec;
|
||||
|
||||
c = atomic64_read(v);
|
||||
for (;;) {
|
||||
dec = c - 1;
|
||||
if (unlikely(dec < 0))
|
||||
break;
|
||||
old = atomic64_cmpxchg((v), c, dec);
|
||||
if (likely(old == c))
|
||||
break;
|
||||
c = old;
|
||||
}
|
||||
return dec;
|
||||
}
|
||||
|
||||
#define ATOMIC_OP(op) \
|
||||
static inline int atomic_fetch_##op(int i, atomic_t *v) \
|
||||
{ \
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
struct task_struct;
|
||||
struct thread_struct;
|
||||
|
||||
#if !defined(CONFIG_LAZY_SAVE_FPU)
|
||||
#if defined(CONFIG_FPU) && !defined(CONFIG_LAZY_SAVE_FPU)
|
||||
struct fpu_state_struct;
|
||||
extern asmlinkage void fpu_save(struct fpu_state_struct *);
|
||||
#define switch_fpu(prev, next) \
|
||||
|
||||
@@ -130,14 +130,16 @@ static void icp_opal_cause_ipi(int cpu, unsigned long data)
|
||||
{
|
||||
int hw_cpu = get_hard_smp_processor_id(cpu);
|
||||
|
||||
kvmppc_set_host_ipi(cpu, 1);
|
||||
opal_int_set_mfrr(hw_cpu, IPI_PRIORITY);
|
||||
}
|
||||
|
||||
static irqreturn_t icp_opal_ipi_action(int irq, void *dev_id)
|
||||
{
|
||||
int hw_cpu = hard_smp_processor_id();
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
opal_int_set_mfrr(hw_cpu, 0xff);
|
||||
kvmppc_set_host_ipi(cpu, 0);
|
||||
opal_int_set_mfrr(get_hard_smp_processor_id(cpu), 0xff);
|
||||
|
||||
return smp_ipi_demux();
|
||||
}
|
||||
|
||||
@@ -240,12 +240,17 @@ ENTRY(sie64a)
|
||||
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
||||
.Lsie_done:
|
||||
# some program checks are suppressing. C code (e.g. do_protection_exception)
|
||||
# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
|
||||
# instructions between sie64a and .Lsie_done should not cause program
|
||||
# interrupts. So lets use a nop (47 00 00 00) as a landing pad.
|
||||
# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
|
||||
# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
|
||||
# Other instructions between sie64a and .Lsie_done should not cause program
|
||||
# interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
|
||||
# See also .Lcleanup_sie
|
||||
.Lrewind_pad:
|
||||
nop 0
|
||||
.Lrewind_pad6:
|
||||
nopr 7
|
||||
.Lrewind_pad4:
|
||||
nopr 7
|
||||
.Lrewind_pad2:
|
||||
nopr 7
|
||||
.globl sie_exit
|
||||
sie_exit:
|
||||
lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
|
||||
@@ -258,7 +263,9 @@ sie_exit:
|
||||
stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
|
||||
j sie_exit
|
||||
|
||||
EX_TABLE(.Lrewind_pad,.Lsie_fault)
|
||||
EX_TABLE(.Lrewind_pad6,.Lsie_fault)
|
||||
EX_TABLE(.Lrewind_pad4,.Lsie_fault)
|
||||
EX_TABLE(.Lrewind_pad2,.Lsie_fault)
|
||||
EX_TABLE(sie_exit,.Lsie_fault)
|
||||
EXPORT_SYMBOL(sie64a)
|
||||
EXPORT_SYMBOL(sie_exit)
|
||||
|
||||
@@ -85,7 +85,7 @@ static void dump_tl1_traplog(struct tl1_traplog *p)
|
||||
|
||||
void bad_trap(struct pt_regs *regs, long lvl)
|
||||
{
|
||||
char buffer[32];
|
||||
char buffer[36];
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "bad trap", regs,
|
||||
@@ -116,7 +116,7 @@ void bad_trap(struct pt_regs *regs, long lvl)
|
||||
|
||||
void bad_trap_tl1(struct pt_regs *regs, long lvl)
|
||||
{
|
||||
char buffer[32];
|
||||
char buffer[36];
|
||||
|
||||
if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
|
||||
0, lvl, SIGTRAP) == NOTIFY_STOP)
|
||||
|
||||
@@ -29,7 +29,8 @@ static inline void variant_irq_disable(unsigned int irq) { }
|
||||
# define PLATFORM_NR_IRQS 0
|
||||
#endif
|
||||
#define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
|
||||
#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS)
|
||||
#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS + 1)
|
||||
#define XTENSA_PIC_LINUX_IRQ(hwirq) ((hwirq) + 1)
|
||||
|
||||
#if VARIANT_NR_IRQS == 0
|
||||
static inline void variant_init_irq(void) { }
|
||||
|
||||
@@ -34,11 +34,6 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
int irq = irq_find_mapping(NULL, hwirq);
|
||||
|
||||
if (hwirq >= NR_IRQS) {
|
||||
printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
|
||||
__func__, hwirq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||
/* Debugging check for stack overflow: is there less than 1KB free? */
|
||||
{
|
||||
|
||||
@@ -24,16 +24,18 @@
|
||||
|
||||
/* Interrupt configuration. */
|
||||
|
||||
#define PLATFORM_NR_IRQS 10
|
||||
#define PLATFORM_NR_IRQS 0
|
||||
|
||||
/* Default assignment of LX60 devices to external interrupts. */
|
||||
|
||||
#ifdef CONFIG_XTENSA_MX
|
||||
#define DUART16552_INTNUM XCHAL_EXTINT3_NUM
|
||||
#define OETH_IRQ XCHAL_EXTINT4_NUM
|
||||
#define C67X00_IRQ XCHAL_EXTINT8_NUM
|
||||
#else
|
||||
#define DUART16552_INTNUM XCHAL_EXTINT0_NUM
|
||||
#define OETH_IRQ XCHAL_EXTINT1_NUM
|
||||
#define C67X00_IRQ XCHAL_EXTINT5_NUM
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -63,5 +65,5 @@
|
||||
|
||||
#define C67X00_PADDR (XCHAL_KIO_PADDR + 0x0D0D0000)
|
||||
#define C67X00_SIZE 0x10
|
||||
#define C67X00_IRQ 5
|
||||
|
||||
#endif /* __XTENSA_XTAVNET_HARDWARE_H */
|
||||
|
||||
@@ -175,8 +175,8 @@ static struct resource ethoc_res[] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[2] = { /* IRQ number */
|
||||
.start = OETH_IRQ,
|
||||
.end = OETH_IRQ,
|
||||
.start = XTENSA_PIC_LINUX_IRQ(OETH_IRQ),
|
||||
.end = XTENSA_PIC_LINUX_IRQ(OETH_IRQ),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
@@ -213,8 +213,8 @@ static struct resource c67x00_res[] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = { /* IRQ number */
|
||||
.start = C67X00_IRQ,
|
||||
.end = C67X00_IRQ,
|
||||
.start = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ),
|
||||
.end = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ),
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
@@ -247,7 +247,7 @@ static struct resource serial_resource = {
|
||||
static struct plat_serial8250_port serial_platform_data[] = {
|
||||
[0] = {
|
||||
.mapbase = DUART16552_PADDR,
|
||||
.irq = DUART16552_INTNUM,
|
||||
.irq = XTENSA_PIC_LINUX_IRQ(DUART16552_INTNUM),
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
|
||||
UPF_IOREMAP,
|
||||
.iotype = XCHAL_HAVE_BE ? UPIO_MEM32BE : UPIO_MEM32,
|
||||
|
||||
@@ -300,6 +300,8 @@ static void parse_bsd(struct parsed_partitions *state,
|
||||
continue;
|
||||
bsd_start = le32_to_cpu(p->p_offset);
|
||||
bsd_size = le32_to_cpu(p->p_size);
|
||||
if (memcmp(flavour, "bsd\0", 4) == 0)
|
||||
bsd_start += offset;
|
||||
if (offset == bsd_start && size == bsd_size)
|
||||
/* full parent partition, we have it already */
|
||||
continue;
|
||||
|
||||
@@ -889,13 +889,13 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
|
||||
if (rpmflags & RPM_GET_PUT) {
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count))
|
||||
return 0;
|
||||
}
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
|
||||
spin_lock_irqsave(&dev->power.lock, flags);
|
||||
retval = rpm_idle(dev, rpmflags);
|
||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||
@@ -921,13 +921,13 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
|
||||
if (rpmflags & RPM_GET_PUT) {
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count))
|
||||
return 0;
|
||||
}
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
|
||||
spin_lock_irqsave(&dev->power.lock, flags);
|
||||
retval = rpm_suspend(dev, rpmflags);
|
||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||
@@ -952,7 +952,8 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
|
||||
dev->power.runtime_status != RPM_ACTIVE);
|
||||
|
||||
if (rpmflags & RPM_GET_PUT)
|
||||
atomic_inc(&dev->power.usage_count);
|
||||
|
||||
@@ -113,6 +113,7 @@ struct ast_private {
|
||||
struct ttm_bo_kmap_obj cache_kmap;
|
||||
int next_cursor;
|
||||
bool support_wide_screen;
|
||||
bool DisableP2A;
|
||||
|
||||
enum ast_tx_chip tx_chip_type;
|
||||
u8 dp501_maxclk;
|
||||
|
||||
@@ -124,6 +124,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
||||
} else
|
||||
*need_post = false;
|
||||
|
||||
/* Check P2A Access */
|
||||
ast->DisableP2A = true;
|
||||
data = ast_read32(ast, 0xf004);
|
||||
if (data != 0xFFFFFFFF)
|
||||
ast->DisableP2A = false;
|
||||
|
||||
/* Check if we support wide screen */
|
||||
switch (ast->chip) {
|
||||
case AST1180:
|
||||
@@ -140,15 +146,17 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
||||
ast->support_wide_screen = true;
|
||||
else {
|
||||
ast->support_wide_screen = false;
|
||||
/* Read SCU7c (silicon revision register) */
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
data = ast_read32(ast, 0x1207c);
|
||||
data &= 0x300;
|
||||
if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
|
||||
ast->support_wide_screen = true;
|
||||
if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
|
||||
ast->support_wide_screen = true;
|
||||
if (ast->DisableP2A == false) {
|
||||
/* Read SCU7c (silicon revision register) */
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
data = ast_read32(ast, 0x1207c);
|
||||
data &= 0x300;
|
||||
if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
|
||||
ast->support_wide_screen = true;
|
||||
if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
|
||||
ast->support_wide_screen = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -216,80 +224,81 @@ static int ast_get_dram_info(struct drm_device *dev)
|
||||
uint32_t data, data2;
|
||||
uint32_t denum, num, div, ref_pll;
|
||||
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
|
||||
|
||||
ast_write32(ast, 0x10000, 0xfc600309);
|
||||
|
||||
do {
|
||||
if (pci_channel_offline(dev->pdev))
|
||||
return -EIO;
|
||||
} while (ast_read32(ast, 0x10000) != 0x01);
|
||||
data = ast_read32(ast, 0x10004);
|
||||
|
||||
if (data & 0x40)
|
||||
if (ast->DisableP2A)
|
||||
{
|
||||
ast->dram_bus_width = 16;
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
ast->mclk = 396;
|
||||
}
|
||||
else
|
||||
ast->dram_bus_width = 32;
|
||||
{
|
||||
ast_write32(ast, 0xf004, 0x1e6e0000);
|
||||
ast_write32(ast, 0xf000, 0x1);
|
||||
data = ast_read32(ast, 0x10004);
|
||||
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400) {
|
||||
switch (data & 0x03) {
|
||||
case 0:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
if (data & 0x40)
|
||||
ast->dram_bus_width = 16;
|
||||
else
|
||||
ast->dram_bus_width = 32;
|
||||
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400) {
|
||||
switch (data & 0x03) {
|
||||
case 0:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
break;
|
||||
case 2:
|
||||
ast->dram_type = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 3:
|
||||
ast->dram_type = AST_DRAM_4Gx16;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (data & 0x0c) {
|
||||
case 0:
|
||||
case 4:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
case 8:
|
||||
if (data & 0x40)
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
else
|
||||
ast->dram_type = AST_DRAM_512Mx32;
|
||||
break;
|
||||
case 0xc:
|
||||
ast->dram_type = AST_DRAM_1Gx32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = ast_read32(ast, 0x10120);
|
||||
data2 = ast_read32(ast, 0x10170);
|
||||
if (data2 & 0x2000)
|
||||
ref_pll = 14318;
|
||||
else
|
||||
ref_pll = 12000;
|
||||
|
||||
denum = data & 0x1f;
|
||||
num = (data & 0x3fe0) >> 5;
|
||||
data = (data & 0xc000) >> 14;
|
||||
switch (data) {
|
||||
case 3:
|
||||
div = 0x4;
|
||||
break;
|
||||
case 2:
|
||||
ast->dram_type = AST_DRAM_2Gx16;
|
||||
case 1:
|
||||
div = 0x2;
|
||||
break;
|
||||
case 3:
|
||||
ast->dram_type = AST_DRAM_4Gx16;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (data & 0x0c) {
|
||||
case 0:
|
||||
case 4:
|
||||
ast->dram_type = AST_DRAM_512Mx16;
|
||||
break;
|
||||
case 8:
|
||||
if (data & 0x40)
|
||||
ast->dram_type = AST_DRAM_1Gx16;
|
||||
else
|
||||
ast->dram_type = AST_DRAM_512Mx32;
|
||||
break;
|
||||
case 0xc:
|
||||
ast->dram_type = AST_DRAM_1Gx32;
|
||||
default:
|
||||
div = 0x1;
|
||||
break;
|
||||
}
|
||||
ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
|
||||
}
|
||||
|
||||
data = ast_read32(ast, 0x10120);
|
||||
data2 = ast_read32(ast, 0x10170);
|
||||
if (data2 & 0x2000)
|
||||
ref_pll = 14318;
|
||||
else
|
||||
ref_pll = 12000;
|
||||
|
||||
denum = data & 0x1f;
|
||||
num = (data & 0x3fe0) >> 5;
|
||||
data = (data & 0xc000) >> 14;
|
||||
switch (data) {
|
||||
case 3:
|
||||
div = 0x4;
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
div = 0x2;
|
||||
break;
|
||||
default:
|
||||
div = 0x1;
|
||||
break;
|
||||
}
|
||||
ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -375,12 +375,20 @@ void ast_post_gpu(struct drm_device *dev)
|
||||
ast_enable_mmio(dev);
|
||||
ast_set_def_ext_reg(dev);
|
||||
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400)
|
||||
ast_init_dram_2300(dev);
|
||||
else
|
||||
ast_init_dram_reg(dev);
|
||||
if (ast->DisableP2A == false)
|
||||
{
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400)
|
||||
ast_init_dram_2300(dev);
|
||||
else
|
||||
ast_init_dram_reg(dev);
|
||||
|
||||
ast_init_3rdtx(dev);
|
||||
ast_init_3rdtx(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ast->tx_chip_type != AST_TX_NONE)
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */
|
||||
}
|
||||
}
|
||||
|
||||
/* AST 2300 DRAM settings */
|
||||
|
||||
@@ -225,6 +225,7 @@ int drm_connector_init(struct drm_device *dev,
|
||||
|
||||
INIT_LIST_HEAD(&connector->probed_modes);
|
||||
INIT_LIST_HEAD(&connector->modes);
|
||||
mutex_init(&connector->mutex);
|
||||
connector->edid_blob_ptr = NULL;
|
||||
connector->status = connector_status_unknown;
|
||||
|
||||
@@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_connector *connector)
|
||||
connector->funcs->atomic_destroy_state(connector,
|
||||
connector->state);
|
||||
|
||||
mutex_destroy(&connector->mutex);
|
||||
|
||||
memset(connector, 0, sizeof(*connector));
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_cleanup);
|
||||
@@ -374,14 +377,18 @@ EXPORT_SYMBOL(drm_connector_cleanup);
|
||||
*/
|
||||
int drm_connector_register(struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (connector->registered)
|
||||
if (!connector->dev->registered)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&connector->mutex);
|
||||
if (connector->registered)
|
||||
goto unlock;
|
||||
|
||||
ret = drm_sysfs_connector_add(connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto unlock;
|
||||
|
||||
ret = drm_debugfs_connector_add(connector);
|
||||
if (ret) {
|
||||
@@ -397,12 +404,14 @@ int drm_connector_register(struct drm_connector *connector)
|
||||
drm_mode_object_register(connector->dev, &connector->base);
|
||||
|
||||
connector->registered = true;
|
||||
return 0;
|
||||
goto unlock;
|
||||
|
||||
err_debugfs:
|
||||
drm_debugfs_connector_remove(connector);
|
||||
err_sysfs:
|
||||
drm_sysfs_connector_remove(connector);
|
||||
unlock:
|
||||
mutex_unlock(&connector->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_register);
|
||||
@@ -415,8 +424,11 @@ EXPORT_SYMBOL(drm_connector_register);
|
||||
*/
|
||||
void drm_connector_unregister(struct drm_connector *connector)
|
||||
{
|
||||
if (!connector->registered)
|
||||
mutex_lock(&connector->mutex);
|
||||
if (!connector->registered) {
|
||||
mutex_unlock(&connector->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connector->funcs->early_unregister)
|
||||
connector->funcs->early_unregister(connector);
|
||||
@@ -425,6 +437,7 @@ void drm_connector_unregister(struct drm_connector *connector)
|
||||
drm_debugfs_connector_remove(connector);
|
||||
|
||||
connector->registered = false;
|
||||
mutex_unlock(&connector->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_unregister);
|
||||
|
||||
|
||||
@@ -710,6 +710,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
|
||||
if (ret)
|
||||
goto err_minors;
|
||||
|
||||
dev->registered = true;
|
||||
|
||||
if (dev->driver->load) {
|
||||
ret = dev->driver->load(dev, flags);
|
||||
if (ret)
|
||||
@@ -749,6 +751,8 @@ void drm_dev_unregister(struct drm_device *dev)
|
||||
|
||||
drm_lastclose(dev);
|
||||
|
||||
dev->registered = false;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_modeset_unregister_all(dev);
|
||||
|
||||
|
||||
@@ -1199,6 +1199,15 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto out_free_priv;
|
||||
|
||||
pci_set_drvdata(pdev, &dev_priv->drm);
|
||||
/*
|
||||
* Disable the system suspend direct complete optimization, which can
|
||||
* leave the device suspended skipping the driver's suspend handlers
|
||||
* if the device was already runtime suspended. This is needed due to
|
||||
* the difference in our runtime and system suspend sequence and
|
||||
* becaue the HDA driver may require us to enable the audio power
|
||||
* domain during system suspend.
|
||||
*/
|
||||
pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
|
||||
|
||||
ret = i915_driver_init_early(dev_priv, ent);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -2253,6 +2253,9 @@ void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
|
||||
intel_fill_fb_ggtt_view(&view, fb, rotation);
|
||||
vma = i915_gem_object_to_ggtt(obj, &view);
|
||||
|
||||
if (WARN_ON_ONCE(!vma))
|
||||
return;
|
||||
|
||||
i915_vma_unpin_fence(vma);
|
||||
i915_gem_object_unpin_from_display_plane(vma);
|
||||
}
|
||||
@@ -13764,6 +13767,15 @@ static void update_scanline_offset(struct intel_crtc *crtc)
|
||||
* type. For DP ports it behaves like most other platforms, but on HDMI
|
||||
* there's an extra 1 line difference. So we need to add two instead of
|
||||
* one to the value.
|
||||
*
|
||||
* On VLV/CHV DSI the scanline counter would appear to increment
|
||||
* approx. 1/3 of a scanline before start of vblank. Unfortunately
|
||||
* that means we can't tell whether we're in vblank or not while
|
||||
* we're on that particular line. We must still set scanline_offset
|
||||
* to 1 so that the vblank timestamps come out correct when we query
|
||||
* the scanline counter from within the vblank interrupt handler.
|
||||
* However if queried just before the start of vblank we'll get an
|
||||
* answer that's slightly in the future.
|
||||
*/
|
||||
if (IS_GEN2(dev)) {
|
||||
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
|
||||
|
||||
@@ -4114,10 +4114,18 @@ skl_compute_wm(struct drm_atomic_state *state)
|
||||
struct drm_crtc_state *cstate;
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct skl_wm_values *results = &intel_state->wm_results;
|
||||
struct drm_device *dev = state->dev;
|
||||
struct skl_pipe_wm *pipe_wm;
|
||||
bool changed = false;
|
||||
int ret, i;
|
||||
|
||||
/*
|
||||
* When we distrust bios wm we always need to recompute to set the
|
||||
* expected DDB allocations for each CRTC.
|
||||
*/
|
||||
if (to_i915(dev)->wm.distrust_bios_wm)
|
||||
changed = true;
|
||||
|
||||
/*
|
||||
* If this transaction isn't actually touching any CRTC's, don't
|
||||
* bother with watermark calculation. Note that if we pass this
|
||||
@@ -4128,6 +4136,7 @@ skl_compute_wm(struct drm_atomic_state *state)
|
||||
*/
|
||||
for_each_crtc_in_state(state, crtc, cstate, i)
|
||||
changed = true;
|
||||
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -81,10 +81,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
||||
*/
|
||||
void intel_pipe_update_start(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
|
||||
long timeout = msecs_to_jiffies_timeout(1);
|
||||
int scanline, min, max, vblank_start;
|
||||
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
|
||||
bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
|
||||
intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI);
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
vblank_start = adjusted_mode->crtc_vblank_start;
|
||||
@@ -136,6 +139,24 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
|
||||
|
||||
drm_crtc_vblank_put(&crtc->base);
|
||||
|
||||
/*
|
||||
* On VLV/CHV DSI the scanline counter would appear to
|
||||
* increment approx. 1/3 of a scanline before start of vblank.
|
||||
* The registers still get latched at start of vblank however.
|
||||
* This means we must not write any registers on the first
|
||||
* line of vblank (since not the whole line is actually in
|
||||
* vblank). And unfortunately we can't use the interrupt to
|
||||
* wait here since it will fire too soon. We could use the
|
||||
* frame start interrupt instead since it will fire after the
|
||||
* critical scanline, but that would require more changes
|
||||
* in the interrupt code. So for now we'll just do the nasty
|
||||
* thing and poll for the bad scanline to pass us by.
|
||||
*
|
||||
* FIXME figure out if BXT+ DSI suffers from this as well
|
||||
*/
|
||||
while (need_vlv_dsi_wa && scanline == vblank_start)
|
||||
scanline = intel_get_crtc_scanline(crtc);
|
||||
|
||||
crtc->debug.scanline_start = scanline;
|
||||
crtc->debug.start_vbl_time = ktime_get();
|
||||
crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <acpi/video.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
@@ -358,6 +359,57 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = {
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static void
|
||||
nouveau_display_hpd_work(struct work_struct *work)
|
||||
{
|
||||
struct nouveau_drm *drm = container_of(work, typeof(*drm), hpd_work);
|
||||
|
||||
pm_runtime_get_sync(drm->dev->dev);
|
||||
|
||||
drm_helper_hpd_irq_event(drm->dev);
|
||||
/* enable polling for external displays */
|
||||
drm_kms_helper_poll_enable(drm->dev);
|
||||
|
||||
pm_runtime_mark_last_busy(drm->dev->dev);
|
||||
pm_runtime_put_sync(drm->dev->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
/*
|
||||
* Hans de Goede: This define belongs in acpi/video.h, I've submitted a patch
|
||||
* to the acpi subsys to move it there from drivers/acpi/acpi_video.c .
|
||||
* This should be dropped once that is merged.
|
||||
*/
|
||||
#ifndef ACPI_VIDEO_NOTIFY_PROBE
|
||||
#define ACPI_VIDEO_NOTIFY_PROBE 0x81
|
||||
#endif
|
||||
|
||||
static int
|
||||
nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
|
||||
void *data)
|
||||
{
|
||||
struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
|
||||
struct acpi_bus_event *info = data;
|
||||
|
||||
if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
|
||||
if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
|
||||
/*
|
||||
* This may be the only indication we receive of a
|
||||
* connector hotplug on a runtime suspended GPU,
|
||||
* schedule hpd_work to check.
|
||||
*/
|
||||
schedule_work(&drm->hpd_work);
|
||||
|
||||
/* acpi-video should not generate keypresses for this */
|
||||
return NOTIFY_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
nouveau_display_init(struct drm_device *dev)
|
||||
{
|
||||
@@ -370,9 +422,6 @@ nouveau_display_init(struct drm_device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* enable polling for external displays */
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
/* enable hotplug interrupts */
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||
@@ -537,6 +586,12 @@ nouveau_display_create(struct drm_device *dev)
|
||||
}
|
||||
|
||||
nouveau_backlight_init(dev);
|
||||
INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
|
||||
#ifdef CONFIG_ACPI
|
||||
drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
|
||||
register_acpi_notifier(&drm->acpi_nb);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
vblank_err:
|
||||
@@ -552,6 +607,9 @@ nouveau_display_destroy(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
|
||||
#endif
|
||||
nouveau_backlight_exit(dev);
|
||||
nouveau_display_vblank_fini(dev);
|
||||
|
||||
|
||||
@@ -483,6 +483,9 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
pm_runtime_allow(dev->dev);
|
||||
pm_runtime_mark_last_busy(dev->dev);
|
||||
pm_runtime_put(dev->dev);
|
||||
} else {
|
||||
/* enable polling for external displays */
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -761,7 +764,7 @@ nouveau_pmops_runtime_resume(struct device *dev)
|
||||
pci_set_master(pdev);
|
||||
|
||||
ret = nouveau_do_resume(drm_dev, true);
|
||||
drm_kms_helper_poll_enable(drm_dev);
|
||||
|
||||
/* do magic */
|
||||
nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
|
||||
vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
* - implemented limited ABI16/NVIF interop
|
||||
*/
|
||||
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#include <nvif/client.h>
|
||||
#include <nvif/device.h>
|
||||
#include <nvif/ioctl.h>
|
||||
@@ -161,6 +163,12 @@ struct nouveau_drm {
|
||||
struct nvbios vbios;
|
||||
struct nouveau_display *display;
|
||||
struct backlight_device *backlight;
|
||||
struct work_struct hpd_work;
|
||||
struct work_struct fbcon_work;
|
||||
int fbcon_new_state;
|
||||
#ifdef CONFIG_ACPI
|
||||
struct notifier_block acpi_nb;
|
||||
#endif
|
||||
|
||||
/* power management */
|
||||
struct nouveau_hwmon *hwmon;
|
||||
|
||||
@@ -491,19 +491,43 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
|
||||
.fb_probe = nouveau_fbcon_create,
|
||||
};
|
||||
|
||||
static void
|
||||
nouveau_fbcon_set_suspend_work(struct work_struct *work)
|
||||
{
|
||||
struct nouveau_drm *drm = container_of(work, typeof(*drm), fbcon_work);
|
||||
int state = READ_ONCE(drm->fbcon_new_state);
|
||||
|
||||
if (state == FBINFO_STATE_RUNNING)
|
||||
pm_runtime_get_sync(drm->dev->dev);
|
||||
|
||||
console_lock();
|
||||
if (state == FBINFO_STATE_RUNNING)
|
||||
nouveau_fbcon_accel_restore(drm->dev);
|
||||
drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
|
||||
if (state != FBINFO_STATE_RUNNING)
|
||||
nouveau_fbcon_accel_save_disable(drm->dev);
|
||||
console_unlock();
|
||||
|
||||
if (state == FBINFO_STATE_RUNNING) {
|
||||
pm_runtime_mark_last_busy(drm->dev->dev);
|
||||
pm_runtime_put_sync(drm->dev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
if (drm->fbcon) {
|
||||
console_lock();
|
||||
if (state == FBINFO_STATE_RUNNING)
|
||||
nouveau_fbcon_accel_restore(dev);
|
||||
drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
|
||||
if (state != FBINFO_STATE_RUNNING)
|
||||
nouveau_fbcon_accel_save_disable(dev);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
if (!drm->fbcon)
|
||||
return;
|
||||
|
||||
drm->fbcon_new_state = state;
|
||||
/* Since runtime resume can happen as a result of a sysfs operation,
|
||||
* it's possible we already have the console locked. So handle fbcon
|
||||
* init/deinit from a seperate work thread
|
||||
*/
|
||||
schedule_work(&drm->fbcon_work);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -524,6 +548,7 @@ nouveau_fbcon_init(struct drm_device *dev)
|
||||
|
||||
fbcon->dev = dev;
|
||||
drm->fbcon = fbcon;
|
||||
INIT_WORK(&drm->fbcon_work, nouveau_fbcon_set_suspend_work);
|
||||
|
||||
drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ struct nv84_fence_priv {
|
||||
struct nouveau_bo *bo;
|
||||
struct nouveau_bo *bo_gart;
|
||||
u32 *suspend;
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
u64 nv84_fence_crtc(struct nouveau_channel *, int);
|
||||
|
||||
@@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
|
||||
if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
|
||||
/* block access to objects not created via this interface */
|
||||
owner = argv->v0.owner;
|
||||
if (argv->v0.object == 0ULL)
|
||||
if (argv->v0.object == 0ULL &&
|
||||
argv->v0.type != NVIF_IOCTL_V0_DEL)
|
||||
argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
|
||||
else
|
||||
argv->v0.owner = NVDRM_OBJECT_USIF;
|
||||
|
||||
@@ -121,8 +121,10 @@ nv84_fence_context_del(struct nouveau_channel *chan)
|
||||
}
|
||||
|
||||
nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
|
||||
mutex_lock(&priv->mutex);
|
||||
nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
|
||||
nouveau_bo_vma_del(priv->bo, &fctx->vma);
|
||||
mutex_unlock(&priv->mutex);
|
||||
nouveau_fence_context_del(&fctx->base);
|
||||
chan->fence = NULL;
|
||||
nouveau_fence_context_free(&fctx->base);
|
||||
@@ -148,11 +150,13 @@ nv84_fence_context_new(struct nouveau_channel *chan)
|
||||
fctx->base.sync32 = nv84_fence_sync32;
|
||||
fctx->base.sequence = nv84_fence_read(chan);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
|
||||
if (ret == 0) {
|
||||
ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
|
||||
&fctx->vma_gart);
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
/* map display semaphore buffers into channel's vm */
|
||||
for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
|
||||
@@ -232,6 +236,8 @@ nv84_fence_create(struct nouveau_drm *drm)
|
||||
priv->base.context_base = fence_context_alloc(priv->base.contexts);
|
||||
priv->base.uevent = true;
|
||||
|
||||
mutex_init(&priv->mutex);
|
||||
|
||||
/* Use VRAM if there is any ; otherwise fallback to system memory */
|
||||
domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
|
||||
/*
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
#define SMBSLVDAT (0xC + piix4_smba)
|
||||
|
||||
/* count for request_region */
|
||||
#define SMBIOSIZE 8
|
||||
#define SMBIOSIZE 9
|
||||
|
||||
/* PCI Address Constants */
|
||||
#define SMBBA 0x090
|
||||
@@ -592,6 +592,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
||||
u8 port;
|
||||
int retval;
|
||||
|
||||
mutex_lock(&piix4_mutex_sb800);
|
||||
|
||||
/* Request the SMBUS semaphore, avoid conflicts with the IMC */
|
||||
smbslvcnt = inb_p(SMBSLVCNT);
|
||||
do {
|
||||
@@ -605,10 +607,10 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
||||
usleep_range(1000, 2000);
|
||||
} while (--retries);
|
||||
/* SMBus is still owned by the IMC, we give up */
|
||||
if (!retries)
|
||||
if (!retries) {
|
||||
mutex_unlock(&piix4_mutex_sb800);
|
||||
return -EBUSY;
|
||||
|
||||
mutex_lock(&piix4_mutex_sb800);
|
||||
}
|
||||
|
||||
outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
|
||||
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
|
||||
@@ -623,11 +625,11 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
||||
|
||||
outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
|
||||
|
||||
mutex_unlock(&piix4_mutex_sb800);
|
||||
|
||||
/* Release the semaphore */
|
||||
outb_p(smbslvcnt | 0x20, SMBSLVCNT);
|
||||
|
||||
mutex_unlock(&piix4_mutex_sb800);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -792,6 +792,9 @@ static struct qedr_dev *qedr_add(struct qed_dev *cdev, struct pci_dev *pdev,
|
||||
if (device_create_file(&dev->ibdev.dev, qedr_attributes[i]))
|
||||
goto sysfs_err;
|
||||
|
||||
if (!test_and_set_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
|
||||
qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ACTIVE);
|
||||
|
||||
DP_DEBUG(dev, QEDR_MSG_INIT, "qedr driver loaded successfully\n");
|
||||
return dev;
|
||||
|
||||
@@ -824,11 +827,10 @@ static void qedr_remove(struct qedr_dev *dev)
|
||||
ib_dealloc_device(&dev->ibdev);
|
||||
}
|
||||
|
||||
static int qedr_close(struct qedr_dev *dev)
|
||||
static void qedr_close(struct qedr_dev *dev)
|
||||
{
|
||||
qedr_ib_dispatch_event(dev, 1, IB_EVENT_PORT_ERR);
|
||||
|
||||
return 0;
|
||||
if (test_and_clear_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
|
||||
qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ERR);
|
||||
}
|
||||
|
||||
static void qedr_shutdown(struct qedr_dev *dev)
|
||||
@@ -837,6 +839,12 @@ static void qedr_shutdown(struct qedr_dev *dev)
|
||||
qedr_remove(dev);
|
||||
}
|
||||
|
||||
static void qedr_open(struct qedr_dev *dev)
|
||||
{
|
||||
if (!test_and_set_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
|
||||
qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ACTIVE);
|
||||
}
|
||||
|
||||
static void qedr_mac_address_change(struct qedr_dev *dev)
|
||||
{
|
||||
union ib_gid *sgid = &dev->sgid_tbl[0];
|
||||
@@ -863,7 +871,7 @@ static void qedr_mac_address_change(struct qedr_dev *dev)
|
||||
|
||||
ether_addr_copy(dev->gsi_ll2_mac_address, dev->ndev->dev_addr);
|
||||
|
||||
qedr_ib_dispatch_event(dev, 1, IB_EVENT_GID_CHANGE);
|
||||
qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_GID_CHANGE);
|
||||
|
||||
if (rc)
|
||||
DP_ERR(dev, "Error updating mac filter\n");
|
||||
@@ -877,7 +885,7 @@ static void qedr_notify(struct qedr_dev *dev, enum qede_roce_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case QEDE_UP:
|
||||
qedr_ib_dispatch_event(dev, 1, IB_EVENT_PORT_ACTIVE);
|
||||
qedr_open(dev);
|
||||
break;
|
||||
case QEDE_DOWN:
|
||||
qedr_close(dev);
|
||||
|
||||
@@ -113,6 +113,8 @@ struct qedr_device_attr {
|
||||
struct qed_rdma_events events;
|
||||
};
|
||||
|
||||
#define QEDR_ENET_STATE_BIT (0)
|
||||
|
||||
struct qedr_dev {
|
||||
struct ib_device ibdev;
|
||||
struct qed_dev *cdev;
|
||||
@@ -153,6 +155,8 @@ struct qedr_dev {
|
||||
struct qedr_cq *gsi_sqcq;
|
||||
struct qedr_cq *gsi_rqcq;
|
||||
struct qedr_qp *gsi_qp;
|
||||
|
||||
unsigned long enet_state;
|
||||
};
|
||||
|
||||
#define QEDR_MAX_SQ_PBL (0x8000)
|
||||
@@ -188,6 +192,7 @@ struct qedr_dev {
|
||||
#define QEDR_ROCE_MAX_CNQ_SIZE (0x4000)
|
||||
|
||||
#define QEDR_MAX_PORT (1)
|
||||
#define QEDR_PORT (1)
|
||||
|
||||
#define QEDR_UVERBS(CMD_NAME) (1ull << IB_USER_VERBS_CMD_##CMD_NAME)
|
||||
|
||||
|
||||
@@ -471,8 +471,6 @@ struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev,
|
||||
struct ib_ucontext *context, struct ib_udata *udata)
|
||||
{
|
||||
struct qedr_dev *dev = get_qedr_dev(ibdev);
|
||||
struct qedr_ucontext *uctx = NULL;
|
||||
struct qedr_alloc_pd_uresp uresp;
|
||||
struct qedr_pd *pd;
|
||||
u16 pd_id;
|
||||
int rc;
|
||||
@@ -489,21 +487,33 @@ struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev,
|
||||
if (!pd)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
dev->ops->rdma_alloc_pd(dev->rdma_ctx, &pd_id);
|
||||
rc = dev->ops->rdma_alloc_pd(dev->rdma_ctx, &pd_id);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
uresp.pd_id = pd_id;
|
||||
pd->pd_id = pd_id;
|
||||
|
||||
if (udata && context) {
|
||||
struct qedr_alloc_pd_uresp uresp;
|
||||
|
||||
uresp.pd_id = pd_id;
|
||||
|
||||
rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
|
||||
if (rc)
|
||||
if (rc) {
|
||||
DP_ERR(dev, "copy error pd_id=0x%x.\n", pd_id);
|
||||
uctx = get_qedr_ucontext(context);
|
||||
uctx->pd = pd;
|
||||
pd->uctx = uctx;
|
||||
dev->ops->rdma_dealloc_pd(dev->rdma_ctx, pd_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pd->uctx = get_qedr_ucontext(context);
|
||||
pd->uctx->pd = pd;
|
||||
}
|
||||
|
||||
return &pd->ibpd;
|
||||
|
||||
err:
|
||||
kfree(pd);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
int qedr_dealloc_pd(struct ib_pd *ibpd)
|
||||
@@ -1719,6 +1729,14 @@ static int qedr_update_qp_state(struct qedr_dev *dev,
|
||||
/* ERR->XXX */
|
||||
switch (new_state) {
|
||||
case QED_ROCE_QP_STATE_RESET:
|
||||
if ((qp->rq.prod != qp->rq.cons) ||
|
||||
(qp->sq.prod != qp->sq.cons)) {
|
||||
DP_NOTICE(dev,
|
||||
"Error->Reset with rq/sq not empty rq.prod=%x rq.cons=%x sq.prod=%x sq.cons=%x\n",
|
||||
qp->rq.prod, qp->rq.cons, qp->sq.prod,
|
||||
qp->sq.cons);
|
||||
status = -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = -EINVAL;
|
||||
@@ -2014,7 +2032,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
|
||||
qp_attr->cap.max_recv_wr = qp->rq.max_wr;
|
||||
qp_attr->cap.max_send_sge = qp->sq.max_sges;
|
||||
qp_attr->cap.max_recv_sge = qp->rq.max_sges;
|
||||
qp_attr->cap.max_inline_data = qp->max_inline_data;
|
||||
qp_attr->cap.max_inline_data = ROCE_REQ_MAX_INLINE_DATA_SIZE;
|
||||
qp_init_attr->cap = qp_attr->cap;
|
||||
|
||||
memcpy(&qp_attr->ah_attr.grh.dgid.raw[0], ¶ms.dgid.bytes[0],
|
||||
@@ -3220,9 +3238,10 @@ static int qedr_poll_cq_req(struct qedr_dev *dev,
|
||||
IB_WC_SUCCESS, 0);
|
||||
break;
|
||||
case RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR:
|
||||
DP_ERR(dev,
|
||||
"Error: POLL CQ with RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR. CQ icid=0x%x, QP icid=0x%x\n",
|
||||
cq->icid, qp->icid);
|
||||
if (qp->state != QED_ROCE_QP_STATE_ERR)
|
||||
DP_ERR(dev,
|
||||
"Error: POLL CQ with RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR. CQ icid=0x%x, QP icid=0x%x\n",
|
||||
cq->icid, qp->icid);
|
||||
cnt = process_req(dev, qp, cq, num_entries, wc, req->sq_cons,
|
||||
IB_WC_WR_FLUSH_ERR, 0);
|
||||
break;
|
||||
|
||||
@@ -142,7 +142,7 @@ static struct irq_chip xtensa_mx_irq_chip = {
|
||||
int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent)
|
||||
{
|
||||
struct irq_domain *root_domain =
|
||||
irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
|
||||
irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
|
||||
&xtensa_mx_irq_domain_ops,
|
||||
&xtensa_mx_irq_chip);
|
||||
irq_set_default_host(root_domain);
|
||||
|
||||
@@ -89,7 +89,7 @@ static struct irq_chip xtensa_irq_chip = {
|
||||
int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent)
|
||||
{
|
||||
struct irq_domain *root_domain =
|
||||
irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
|
||||
irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
|
||||
&xtensa_irq_domain_ops, &xtensa_irq_chip);
|
||||
irq_set_default_host(root_domain);
|
||||
return 0;
|
||||
|
||||
@@ -1153,6 +1153,12 @@ static void init_ring(struct net_device *dev)
|
||||
if (skb == NULL)
|
||||
break;
|
||||
np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||
if (pci_dma_mapping_error(np->pci_dev,
|
||||
np->rx_info[i].mapping)) {
|
||||
dev_kfree_skb(skb);
|
||||
np->rx_info[i].skb = NULL;
|
||||
break;
|
||||
}
|
||||
/* Grrr, we cannot offset to correctly align the IP header. */
|
||||
np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
|
||||
}
|
||||
@@ -1183,8 +1189,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct netdev_private *np = netdev_priv(dev);
|
||||
unsigned int entry;
|
||||
unsigned int prev_tx;
|
||||
u32 status;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* be cautious here, wrapping the queue has weird semantics
|
||||
@@ -1202,6 +1209,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
|
||||
|
||||
prev_tx = np->cur_tx;
|
||||
entry = np->cur_tx % TX_RING_SIZE;
|
||||
for (i = 0; i < skb_num_frags(skb); i++) {
|
||||
int wrap_ring = 0;
|
||||
@@ -1235,6 +1243,11 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
skb_frag_size(this_frag),
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
if (pci_dma_mapping_error(np->pci_dev,
|
||||
np->tx_info[entry].mapping)) {
|
||||
dev->stats.tx_dropped++;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
|
||||
np->tx_ring[entry].status = cpu_to_le32(status);
|
||||
@@ -1269,8 +1282,30 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
netif_stop_queue(dev);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
err_out:
|
||||
entry = prev_tx % TX_RING_SIZE;
|
||||
np->tx_info[entry].skb = NULL;
|
||||
if (i > 0) {
|
||||
pci_unmap_single(np->pci_dev,
|
||||
np->tx_info[entry].mapping,
|
||||
skb_first_frag_len(skb),
|
||||
PCI_DMA_TODEVICE);
|
||||
np->tx_info[entry].mapping = 0;
|
||||
entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
|
||||
for (j = 1; j < i; j++) {
|
||||
pci_unmap_single(np->pci_dev,
|
||||
np->tx_info[entry].mapping,
|
||||
skb_frag_size(
|
||||
&skb_shinfo(skb)->frags[j-1]),
|
||||
PCI_DMA_TODEVICE);
|
||||
entry++;
|
||||
}
|
||||
}
|
||||
dev_kfree_skb_any(skb);
|
||||
np->cur_tx = prev_tx;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/* The interrupt handler does all of the Rx thread work and cleans up
|
||||
after the Tx thread. */
|
||||
@@ -1570,6 +1605,12 @@ static void refill_rx_ring(struct net_device *dev)
|
||||
break; /* Better luck next round. */
|
||||
np->rx_info[entry].mapping =
|
||||
pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||
if (pci_dma_mapping_error(np->pci_dev,
|
||||
np->rx_info[entry].mapping)) {
|
||||
dev_kfree_skb(skb);
|
||||
np->rx_info[entry].skb = NULL;
|
||||
break;
|
||||
}
|
||||
np->rx_ring[entry].rxaddr =
|
||||
cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
|
||||
}
|
||||
|
||||
@@ -1499,6 +1499,7 @@ static int bnxt_async_event_process(struct bnxt *bp,
|
||||
netdev_warn(bp->dev, "Link speed %d no longer supported\n",
|
||||
speed);
|
||||
}
|
||||
set_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT, &bp->sp_event);
|
||||
/* fall thru */
|
||||
}
|
||||
case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
|
||||
@@ -5110,6 +5111,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
|
||||
struct hwrm_port_phy_qcfg_input req = {0};
|
||||
struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
|
||||
u8 link_up = link_info->link_up;
|
||||
u16 diff;
|
||||
|
||||
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1);
|
||||
|
||||
@@ -5197,6 +5199,18 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
|
||||
link_info->link_up = 0;
|
||||
}
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
|
||||
diff = link_info->support_auto_speeds ^ link_info->advertising;
|
||||
if ((link_info->support_auto_speeds | diff) !=
|
||||
link_info->support_auto_speeds) {
|
||||
/* An advertised speed is no longer supported, so we need to
|
||||
* update the advertisement settings. Caller holds RTNL
|
||||
* so we can modify link settings.
|
||||
*/
|
||||
link_info->advertising = link_info->support_auto_speeds;
|
||||
if (link_info->autoneg & BNXT_AUTONEG_SPEED)
|
||||
bnxt_hwrm_set_link_setting(bp, true, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6080,29 +6094,37 @@ bnxt_restart_timer:
|
||||
mod_timer(&bp->timer, jiffies + bp->current_interval);
|
||||
}
|
||||
|
||||
/* Only called from bnxt_sp_task() */
|
||||
static void bnxt_reset(struct bnxt *bp, bool silent)
|
||||
static void bnxt_rtnl_lock_sp(struct bnxt *bp)
|
||||
{
|
||||
/* bnxt_reset_task() calls bnxt_close_nic() which waits
|
||||
* for BNXT_STATE_IN_SP_TASK to clear.
|
||||
* If there is a parallel dev_close(), bnxt_close() may be holding
|
||||
/* We are called from bnxt_sp_task which has BNXT_STATE_IN_SP_TASK
|
||||
* set. If the device is being closed, bnxt_close() may be holding
|
||||
* rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear. So we
|
||||
* must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
|
||||
*/
|
||||
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
|
||||
rtnl_lock();
|
||||
if (test_bit(BNXT_STATE_OPEN, &bp->state))
|
||||
bnxt_reset_task(bp, silent);
|
||||
}
|
||||
|
||||
static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
|
||||
{
|
||||
set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/* Only called from bnxt_sp_task() */
|
||||
static void bnxt_reset(struct bnxt *bp, bool silent)
|
||||
{
|
||||
bnxt_rtnl_lock_sp(bp);
|
||||
if (test_bit(BNXT_STATE_OPEN, &bp->state))
|
||||
bnxt_reset_task(bp, silent);
|
||||
bnxt_rtnl_unlock_sp(bp);
|
||||
}
|
||||
|
||||
static void bnxt_cfg_ntp_filters(struct bnxt *);
|
||||
|
||||
static void bnxt_sp_task(struct work_struct *work)
|
||||
{
|
||||
struct bnxt *bp = container_of(work, struct bnxt, sp_task);
|
||||
int rc;
|
||||
|
||||
set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
|
||||
smp_mb__after_atomic();
|
||||
@@ -6116,12 +6138,6 @@ static void bnxt_sp_task(struct work_struct *work)
|
||||
|
||||
if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event))
|
||||
bnxt_cfg_ntp_filters(bp);
|
||||
if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
|
||||
rc = bnxt_update_link(bp, true);
|
||||
if (rc)
|
||||
netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
|
||||
rc);
|
||||
}
|
||||
if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
|
||||
bnxt_hwrm_exec_fwd_req(bp);
|
||||
if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
|
||||
@@ -6142,18 +6158,39 @@ static void bnxt_sp_task(struct work_struct *work)
|
||||
bnxt_hwrm_tunnel_dst_port_free(
|
||||
bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
|
||||
}
|
||||
if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
|
||||
bnxt_hwrm_port_qstats(bp);
|
||||
|
||||
/* These functions below will clear BNXT_STATE_IN_SP_TASK. They
|
||||
* must be the last functions to be called before exiting.
|
||||
*/
|
||||
if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
|
||||
int rc = 0;
|
||||
|
||||
if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
|
||||
&bp->sp_event))
|
||||
bnxt_hwrm_phy_qcaps(bp);
|
||||
|
||||
bnxt_rtnl_lock_sp(bp);
|
||||
if (test_bit(BNXT_STATE_OPEN, &bp->state))
|
||||
rc = bnxt_update_link(bp, true);
|
||||
bnxt_rtnl_unlock_sp(bp);
|
||||
if (rc)
|
||||
netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
|
||||
rc);
|
||||
}
|
||||
if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) {
|
||||
bnxt_rtnl_lock_sp(bp);
|
||||
if (test_bit(BNXT_STATE_OPEN, &bp->state))
|
||||
bnxt_get_port_module_status(bp);
|
||||
bnxt_rtnl_unlock_sp(bp);
|
||||
}
|
||||
if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
|
||||
bnxt_reset(bp, false);
|
||||
|
||||
if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
|
||||
bnxt_reset(bp, true);
|
||||
|
||||
if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
|
||||
bnxt_get_port_module_status(bp);
|
||||
|
||||
if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
|
||||
bnxt_hwrm_port_qstats(bp);
|
||||
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
|
||||
}
|
||||
|
||||
@@ -1089,6 +1089,7 @@ struct bnxt {
|
||||
#define BNXT_RESET_TASK_SILENT_SP_EVENT 11
|
||||
#define BNXT_GENEVE_ADD_PORT_SP_EVENT 12
|
||||
#define BNXT_GENEVE_DEL_PORT_SP_EVENT 13
|
||||
#define BNXT_LINK_SPEED_CHNG_SP_EVENT 14
|
||||
|
||||
struct bnxt_pf_info pf;
|
||||
#ifdef CONFIG_BNXT_SRIOV
|
||||
|
||||
@@ -31,6 +31,7 @@ struct lmac {
|
||||
u8 lmac_type;
|
||||
u8 lane_to_sds;
|
||||
bool use_training;
|
||||
bool autoneg;
|
||||
bool link_up;
|
||||
int lmacid; /* ID within BGX */
|
||||
int lmacid_bd; /* ID on board */
|
||||
@@ -418,7 +419,17 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
|
||||
/* power down, reset autoneg, autoneg enable */
|
||||
cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MRX_CTL);
|
||||
cfg &= ~PCS_MRX_CTL_PWR_DN;
|
||||
cfg |= (PCS_MRX_CTL_RST_AN | PCS_MRX_CTL_AN_EN);
|
||||
cfg |= PCS_MRX_CTL_RST_AN;
|
||||
if (lmac->phydev) {
|
||||
cfg |= PCS_MRX_CTL_AN_EN;
|
||||
} else {
|
||||
/* In scenarios where PHY driver is not present or it's a
|
||||
* non-standard PHY, FW sets AN_EN to inform Linux driver
|
||||
* to do auto-neg and link polling or not.
|
||||
*/
|
||||
if (cfg & PCS_MRX_CTL_AN_EN)
|
||||
lmac->autoneg = true;
|
||||
}
|
||||
bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg);
|
||||
|
||||
if (lmac->lmac_type == BGX_MODE_QSGMII) {
|
||||
@@ -429,7 +440,7 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lmac->lmac_type == BGX_MODE_SGMII) {
|
||||
if ((lmac->lmac_type == BGX_MODE_SGMII) && lmac->phydev) {
|
||||
if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
|
||||
PCS_MRX_STATUS_AN_CPT, false)) {
|
||||
dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
|
||||
@@ -623,12 +634,71 @@ static int bgx_xaui_check_link(struct lmac *lmac)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void bgx_poll_for_sgmii_link(struct lmac *lmac)
|
||||
{
|
||||
u64 pcs_link, an_result;
|
||||
u8 speed;
|
||||
|
||||
pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
|
||||
BGX_GMP_PCS_MRX_STATUS);
|
||||
|
||||
/*Link state bit is sticky, read it again*/
|
||||
if (!(pcs_link & PCS_MRX_STATUS_LINK))
|
||||
pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
|
||||
BGX_GMP_PCS_MRX_STATUS);
|
||||
|
||||
if (bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_GMP_PCS_MRX_STATUS,
|
||||
PCS_MRX_STATUS_AN_CPT, false)) {
|
||||
lmac->link_up = false;
|
||||
lmac->last_speed = SPEED_UNKNOWN;
|
||||
lmac->last_duplex = DUPLEX_UNKNOWN;
|
||||
goto next_poll;
|
||||
}
|
||||
|
||||
lmac->link_up = ((pcs_link & PCS_MRX_STATUS_LINK) != 0) ? true : false;
|
||||
an_result = bgx_reg_read(lmac->bgx, lmac->lmacid,
|
||||
BGX_GMP_PCS_ANX_AN_RESULTS);
|
||||
|
||||
speed = (an_result >> 3) & 0x3;
|
||||
lmac->last_duplex = (an_result >> 1) & 0x1;
|
||||
switch (speed) {
|
||||
case 0:
|
||||
lmac->last_speed = 10;
|
||||
break;
|
||||
case 1:
|
||||
lmac->last_speed = 100;
|
||||
break;
|
||||
case 2:
|
||||
lmac->last_speed = 1000;
|
||||
break;
|
||||
default:
|
||||
lmac->link_up = false;
|
||||
lmac->last_speed = SPEED_UNKNOWN;
|
||||
lmac->last_duplex = DUPLEX_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
next_poll:
|
||||
|
||||
if (lmac->last_link != lmac->link_up) {
|
||||
if (lmac->link_up)
|
||||
bgx_sgmii_change_link_state(lmac);
|
||||
lmac->last_link = lmac->link_up;
|
||||
}
|
||||
|
||||
queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 3);
|
||||
}
|
||||
|
||||
static void bgx_poll_for_link(struct work_struct *work)
|
||||
{
|
||||
struct lmac *lmac;
|
||||
u64 spu_link, smu_link;
|
||||
|
||||
lmac = container_of(work, struct lmac, dwork.work);
|
||||
if (lmac->is_sgmii) {
|
||||
bgx_poll_for_sgmii_link(lmac);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Receive link is latching low. Force it high and verify it */
|
||||
bgx_reg_modify(lmac->bgx, lmac->lmacid,
|
||||
@@ -720,9 +790,21 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
|
||||
(lmac->lmac_type != BGX_MODE_XLAUI) &&
|
||||
(lmac->lmac_type != BGX_MODE_40G_KR) &&
|
||||
(lmac->lmac_type != BGX_MODE_10G_KR)) {
|
||||
if (!lmac->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
if (!lmac->phydev) {
|
||||
if (lmac->autoneg) {
|
||||
bgx_reg_write(bgx, lmacid,
|
||||
BGX_GMP_PCS_LINKX_TIMER,
|
||||
PCS_LINKX_TIMER_COUNT);
|
||||
goto poll;
|
||||
} else {
|
||||
/* Default to below link speed and duplex */
|
||||
lmac->link_up = true;
|
||||
lmac->last_speed = 1000;
|
||||
lmac->last_duplex = 1;
|
||||
bgx_sgmii_change_link_state(lmac);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lmac->phydev->dev_flags = 0;
|
||||
|
||||
if (phy_connect_direct(&lmac->netdev, lmac->phydev,
|
||||
@@ -731,15 +813,17 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
|
||||
return -ENODEV;
|
||||
|
||||
phy_start_aneg(lmac->phydev);
|
||||
} else {
|
||||
lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
|
||||
WQ_MEM_RECLAIM, 1);
|
||||
if (!lmac->check_link)
|
||||
return -ENOMEM;
|
||||
INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
|
||||
queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
poll:
|
||||
lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
|
||||
WQ_MEM_RECLAIM, 1);
|
||||
if (!lmac->check_link)
|
||||
return -ENOMEM;
|
||||
INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
|
||||
queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,10 +144,15 @@
|
||||
#define PCS_MRX_CTL_LOOPBACK1 BIT_ULL(14)
|
||||
#define PCS_MRX_CTL_RESET BIT_ULL(15)
|
||||
#define BGX_GMP_PCS_MRX_STATUS 0x30008
|
||||
#define PCS_MRX_STATUS_LINK BIT_ULL(2)
|
||||
#define PCS_MRX_STATUS_AN_CPT BIT_ULL(5)
|
||||
#define BGX_GMP_PCS_ANX_ADV 0x30010
|
||||
#define BGX_GMP_PCS_ANX_AN_RESULTS 0x30020
|
||||
#define BGX_GMP_PCS_LINKX_TIMER 0x30040
|
||||
#define PCS_LINKX_TIMER_COUNT 0x1E84
|
||||
#define BGX_GMP_PCS_SGM_AN_ADV 0x30068
|
||||
#define BGX_GMP_PCS_MISCX_CTL 0x30078
|
||||
#define PCS_MISC_CTL_MODE BIT_ULL(8)
|
||||
#define PCS_MISC_CTL_DISP_EN BIT_ULL(13)
|
||||
#define PCS_MISC_CTL_GMX_ENO BIT_ULL(11)
|
||||
#define PCS_MISC_CTL_SAMP_PT_MASK 0x7Full
|
||||
|
||||
@@ -2007,8 +2007,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
|
||||
if (!rxb->page)
|
||||
continue;
|
||||
|
||||
dma_unmap_single(rx_queue->dev, rxb->dma,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
dma_unmap_page(rx_queue->dev, rxb->dma,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
__free_page(rxb->page);
|
||||
|
||||
rxb->page = NULL;
|
||||
|
||||
@@ -304,8 +304,8 @@ int hns_nic_net_xmit_hw(struct net_device *ndev,
|
||||
struct hns_nic_ring_data *ring_data)
|
||||
{
|
||||
struct hns_nic_priv *priv = netdev_priv(ndev);
|
||||
struct device *dev = priv->dev;
|
||||
struct hnae_ring *ring = ring_data->ring;
|
||||
struct device *dev = ring_to_dev(ring);
|
||||
struct netdev_queue *dev_queue;
|
||||
struct skb_frag_struct *frag;
|
||||
int buf_num;
|
||||
|
||||
@@ -189,9 +189,10 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
|
||||
}
|
||||
ltb->map_id = adapter->map_id;
|
||||
adapter->map_id++;
|
||||
|
||||
init_completion(&adapter->fw_done);
|
||||
send_request_map(adapter, ltb->addr,
|
||||
ltb->size, ltb->map_id);
|
||||
init_completion(&adapter->fw_done);
|
||||
wait_for_completion(&adapter->fw_done);
|
||||
return 0;
|
||||
}
|
||||
@@ -505,7 +506,7 @@ rx_pool_alloc_failed:
|
||||
adapter->rx_pool = NULL;
|
||||
rx_pool_arr_alloc_failed:
|
||||
for (i = 0; i < adapter->req_rx_queues; i++)
|
||||
napi_enable(&adapter->napi[i]);
|
||||
napi_disable(&adapter->napi[i]);
|
||||
alloc_napi_failed:
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -1133,10 +1134,10 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
|
||||
crq.request_statistics.ioba = cpu_to_be32(adapter->stats_token);
|
||||
crq.request_statistics.len =
|
||||
cpu_to_be32(sizeof(struct ibmvnic_statistics));
|
||||
ibmvnic_send_crq(adapter, &crq);
|
||||
|
||||
/* Wait for data to be written */
|
||||
init_completion(&adapter->stats_done);
|
||||
ibmvnic_send_crq(adapter, &crq);
|
||||
wait_for_completion(&adapter->stats_done);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
|
||||
@@ -2197,12 +2198,12 @@ static void handle_error_info_rsp(union ibmvnic_crq *crq,
|
||||
|
||||
if (!found) {
|
||||
dev_err(dev, "Couldn't find error id %x\n",
|
||||
crq->request_error_rsp.error_id);
|
||||
be32_to_cpu(crq->request_error_rsp.error_id));
|
||||
return;
|
||||
}
|
||||
|
||||
dev_err(dev, "Detailed info for error id %x:",
|
||||
crq->request_error_rsp.error_id);
|
||||
be32_to_cpu(crq->request_error_rsp.error_id));
|
||||
|
||||
for (i = 0; i < error_buff->len; i++) {
|
||||
pr_cont("%02x", (int)error_buff->buff[i]);
|
||||
@@ -2281,8 +2282,8 @@ static void handle_error_indication(union ibmvnic_crq *crq,
|
||||
dev_err(dev, "Firmware reports %serror id %x, cause %d\n",
|
||||
crq->error_indication.
|
||||
flags & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
|
||||
crq->error_indication.error_id,
|
||||
crq->error_indication.error_cause);
|
||||
be32_to_cpu(crq->error_indication.error_id),
|
||||
be16_to_cpu(crq->error_indication.error_cause));
|
||||
|
||||
error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC);
|
||||
if (!error_buff)
|
||||
@@ -2400,10 +2401,10 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq,
|
||||
case PARTIALSUCCESS:
|
||||
dev_info(dev, "req=%lld, rsp=%ld in %s queue, retrying.\n",
|
||||
*req_value,
|
||||
(long int)be32_to_cpu(crq->request_capability_rsp.
|
||||
(long int)be64_to_cpu(crq->request_capability_rsp.
|
||||
number), name);
|
||||
release_sub_crqs_no_irqs(adapter);
|
||||
*req_value = be32_to_cpu(crq->request_capability_rsp.number);
|
||||
*req_value = be64_to_cpu(crq->request_capability_rsp.number);
|
||||
init_sub_crqs(adapter, 1);
|
||||
return;
|
||||
default:
|
||||
@@ -2809,9 +2810,9 @@ static ssize_t trace_read(struct file *file, char __user *user_buf, size_t len,
|
||||
crq.collect_fw_trace.correlator = adapter->ras_comps[num].correlator;
|
||||
crq.collect_fw_trace.ioba = cpu_to_be32(trace_tok);
|
||||
crq.collect_fw_trace.len = adapter->ras_comps[num].trace_buff_size;
|
||||
ibmvnic_send_crq(adapter, &crq);
|
||||
|
||||
init_completion(&adapter->fw_done);
|
||||
ibmvnic_send_crq(adapter, &crq);
|
||||
wait_for_completion(&adapter->fw_done);
|
||||
|
||||
if (*ppos + len > be32_to_cpu(adapter->ras_comps[num].trace_buff_size))
|
||||
@@ -3591,9 +3592,9 @@ static int ibmvnic_dump_show(struct seq_file *seq, void *v)
|
||||
memset(&crq, 0, sizeof(crq));
|
||||
crq.request_dump_size.first = IBMVNIC_CRQ_CMD;
|
||||
crq.request_dump_size.cmd = REQUEST_DUMP_SIZE;
|
||||
ibmvnic_send_crq(adapter, &crq);
|
||||
|
||||
init_completion(&adapter->fw_done);
|
||||
ibmvnic_send_crq(adapter, &crq);
|
||||
wait_for_completion(&adapter->fw_done);
|
||||
|
||||
seq_write(seq, adapter->dump_data, adapter->dump_data_size);
|
||||
@@ -3639,8 +3640,8 @@ static void handle_crq_init_rsp(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
send_version_xchg(adapter);
|
||||
reinit_completion(&adapter->init_done);
|
||||
send_version_xchg(adapter);
|
||||
if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
|
||||
dev_err(dev, "Passive init timeout\n");
|
||||
goto task_failed;
|
||||
@@ -3650,9 +3651,9 @@ static void handle_crq_init_rsp(struct work_struct *work)
|
||||
if (adapter->renegotiate) {
|
||||
adapter->renegotiate = false;
|
||||
release_sub_crqs_no_irqs(adapter);
|
||||
send_cap_queries(adapter);
|
||||
|
||||
reinit_completion(&adapter->init_done);
|
||||
send_cap_queries(adapter);
|
||||
if (!wait_for_completion_timeout(&adapter->init_done,
|
||||
timeout)) {
|
||||
dev_err(dev, "Passive init timeout\n");
|
||||
@@ -3780,9 +3781,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
|
||||
adapter->debugfs_dump = ent;
|
||||
}
|
||||
}
|
||||
ibmvnic_send_crq_init(adapter);
|
||||
|
||||
init_completion(&adapter->init_done);
|
||||
ibmvnic_send_crq_init(adapter);
|
||||
if (!wait_for_completion_timeout(&adapter->init_done, timeout))
|
||||
return 0;
|
||||
|
||||
@@ -3790,9 +3791,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
|
||||
if (adapter->renegotiate) {
|
||||
adapter->renegotiate = false;
|
||||
release_sub_crqs_no_irqs(adapter);
|
||||
send_cap_queries(adapter);
|
||||
|
||||
reinit_completion(&adapter->init_done);
|
||||
send_cap_queries(adapter);
|
||||
if (!wait_for_completion_timeout(&adapter->init_done,
|
||||
timeout))
|
||||
return 0;
|
||||
|
||||
@@ -2518,7 +2518,7 @@ static int mtk_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
const struct of_device_id of_mtk_match[] = {
|
||||
{ .compatible = "mediatek,mt7623-eth" },
|
||||
{ .compatible = "mediatek,mt2701-eth" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_mtk_match);
|
||||
|
||||
@@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_dev *dev)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int mlx4_comm_internal_err(u32 slave_read)
|
||||
int mlx4_comm_internal_err(u32 slave_read)
|
||||
{
|
||||
return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
|
||||
(slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
|
||||
|
||||
@@ -222,6 +222,18 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
|
||||
return;
|
||||
|
||||
mlx4_stop_catas_poll(dev);
|
||||
if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
|
||||
mlx4_is_slave(dev)) {
|
||||
/* In mlx4_remove_one on a VF */
|
||||
u32 slave_read =
|
||||
swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
|
||||
|
||||
if (mlx4_comm_internal_err(slave_read)) {
|
||||
mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
|
||||
__func__);
|
||||
mlx4_enter_error_state(dev->persist);
|
||||
}
|
||||
}
|
||||
mutex_lock(&intf_mutex);
|
||||
|
||||
list_for_each_entry(intf, &intf_list, list)
|
||||
|
||||
@@ -1220,6 +1220,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type);
|
||||
void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
|
||||
|
||||
void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
|
||||
int mlx4_comm_internal_err(u32 slave_read);
|
||||
|
||||
int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
|
||||
enum mlx4_port_type *type);
|
||||
|
||||
@@ -1081,7 +1081,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
|
||||
MLX5_FLOW_NAMESPACE_KERNEL);
|
||||
|
||||
if (!priv->fs.ns)
|
||||
return -EINVAL;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = mlx5e_arfs_create_tables(priv);
|
||||
if (err) {
|
||||
|
||||
@@ -352,7 +352,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw, int nvports)
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
return -ENOMEM;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = mlx5_vzalloc(inlen);
|
||||
@@ -961,7 +961,7 @@ static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_EGRESS);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get E-Switch egress flow namespace\n");
|
||||
return -EIO;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = mlx5_vzalloc(inlen);
|
||||
@@ -1078,7 +1078,7 @@ static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get E-Switch ingress flow namespace\n");
|
||||
return -EIO;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = mlx5_vzalloc(inlen);
|
||||
|
||||
@@ -414,6 +414,7 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
err = -EOPNOTSUPP;
|
||||
goto ns_err;
|
||||
}
|
||||
|
||||
@@ -520,7 +521,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw)
|
||||
ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
|
||||
if (!ns) {
|
||||
esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
|
||||
return -ENOMEM;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0);
|
||||
@@ -639,7 +640,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw)
|
||||
esw_warn(esw->dev, "Failed setting eswitch to offloads, err %d\n", err);
|
||||
err1 = mlx5_eswitch_enable_sriov(esw, num_vfs, SRIOV_LEGACY);
|
||||
if (err1)
|
||||
esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err);
|
||||
esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err1);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1678,7 +1678,7 @@ static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
|
||||
struct mlx5_flow_table *ft;
|
||||
|
||||
ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
|
||||
if (!ns)
|
||||
if (WARN_ON(!ns))
|
||||
return -EINVAL;
|
||||
ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL);
|
||||
if (IS_ERR(ft)) {
|
||||
|
||||
@@ -179,6 +179,49 @@ static struct mdiobb_ops bb_ops = {
|
||||
.get_mdio_data = ravb_get_mdio_data,
|
||||
};
|
||||
|
||||
/* Free TX skb function for AVB-IP */
|
||||
static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
struct net_device_stats *stats = &priv->stats[q];
|
||||
struct ravb_tx_desc *desc;
|
||||
int free_num = 0;
|
||||
int entry;
|
||||
u32 size;
|
||||
|
||||
for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
|
||||
bool txed;
|
||||
|
||||
entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
|
||||
NUM_TX_DESC);
|
||||
desc = &priv->tx_ring[q][entry];
|
||||
txed = desc->die_dt == DT_FEMPTY;
|
||||
if (free_txed_only && !txed)
|
||||
break;
|
||||
/* Descriptor type must be checked before all other reads */
|
||||
dma_rmb();
|
||||
size = le16_to_cpu(desc->ds_tagl) & TX_DS;
|
||||
/* Free the original skb. */
|
||||
if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
|
||||
dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
|
||||
size, DMA_TO_DEVICE);
|
||||
/* Last packet descriptor? */
|
||||
if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
|
||||
entry /= NUM_TX_DESC;
|
||||
dev_kfree_skb_any(priv->tx_skb[q][entry]);
|
||||
priv->tx_skb[q][entry] = NULL;
|
||||
if (txed)
|
||||
stats->tx_packets++;
|
||||
}
|
||||
free_num++;
|
||||
}
|
||||
if (txed)
|
||||
stats->tx_bytes += size;
|
||||
desc->die_dt = DT_EEMPTY;
|
||||
}
|
||||
return free_num;
|
||||
}
|
||||
|
||||
/* Free skb's and DMA buffers for Ethernet AVB */
|
||||
static void ravb_ring_free(struct net_device *ndev, int q)
|
||||
{
|
||||
@@ -194,19 +237,21 @@ static void ravb_ring_free(struct net_device *ndev, int q)
|
||||
kfree(priv->rx_skb[q]);
|
||||
priv->rx_skb[q] = NULL;
|
||||
|
||||
/* Free TX skb ringbuffer */
|
||||
if (priv->tx_skb[q]) {
|
||||
for (i = 0; i < priv->num_tx_ring[q]; i++)
|
||||
dev_kfree_skb(priv->tx_skb[q][i]);
|
||||
}
|
||||
kfree(priv->tx_skb[q]);
|
||||
priv->tx_skb[q] = NULL;
|
||||
|
||||
/* Free aligned TX buffers */
|
||||
kfree(priv->tx_align[q]);
|
||||
priv->tx_align[q] = NULL;
|
||||
|
||||
if (priv->rx_ring[q]) {
|
||||
for (i = 0; i < priv->num_rx_ring[q]; i++) {
|
||||
struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
|
||||
|
||||
if (!dma_mapping_error(ndev->dev.parent,
|
||||
le32_to_cpu(desc->dptr)))
|
||||
dma_unmap_single(ndev->dev.parent,
|
||||
le32_to_cpu(desc->dptr),
|
||||
PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
ring_size = sizeof(struct ravb_ex_rx_desc) *
|
||||
(priv->num_rx_ring[q] + 1);
|
||||
dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
|
||||
@@ -215,12 +260,20 @@ static void ravb_ring_free(struct net_device *ndev, int q)
|
||||
}
|
||||
|
||||
if (priv->tx_ring[q]) {
|
||||
ravb_tx_free(ndev, q, false);
|
||||
|
||||
ring_size = sizeof(struct ravb_tx_desc) *
|
||||
(priv->num_tx_ring[q] * NUM_TX_DESC + 1);
|
||||
dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q],
|
||||
priv->tx_desc_dma[q]);
|
||||
priv->tx_ring[q] = NULL;
|
||||
}
|
||||
|
||||
/* Free TX skb ringbuffer.
|
||||
* SKBs are freed by ravb_tx_free() call above.
|
||||
*/
|
||||
kfree(priv->tx_skb[q]);
|
||||
priv->tx_skb[q] = NULL;
|
||||
}
|
||||
|
||||
/* Format skb and descriptor buffer for Ethernet AVB */
|
||||
@@ -431,44 +484,6 @@ static int ravb_dmac_init(struct net_device *ndev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free TX skb function for AVB-IP */
|
||||
static int ravb_tx_free(struct net_device *ndev, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
struct net_device_stats *stats = &priv->stats[q];
|
||||
struct ravb_tx_desc *desc;
|
||||
int free_num = 0;
|
||||
int entry;
|
||||
u32 size;
|
||||
|
||||
for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
|
||||
entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
|
||||
NUM_TX_DESC);
|
||||
desc = &priv->tx_ring[q][entry];
|
||||
if (desc->die_dt != DT_FEMPTY)
|
||||
break;
|
||||
/* Descriptor type must be checked before all other reads */
|
||||
dma_rmb();
|
||||
size = le16_to_cpu(desc->ds_tagl) & TX_DS;
|
||||
/* Free the original skb. */
|
||||
if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
|
||||
dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
|
||||
size, DMA_TO_DEVICE);
|
||||
/* Last packet descriptor? */
|
||||
if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
|
||||
entry /= NUM_TX_DESC;
|
||||
dev_kfree_skb_any(priv->tx_skb[q][entry]);
|
||||
priv->tx_skb[q][entry] = NULL;
|
||||
stats->tx_packets++;
|
||||
}
|
||||
free_num++;
|
||||
}
|
||||
stats->tx_bytes += size;
|
||||
desc->die_dt = DT_EEMPTY;
|
||||
}
|
||||
return free_num;
|
||||
}
|
||||
|
||||
static void ravb_get_tx_tstamp(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
@@ -902,7 +917,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
/* Clear TX interrupt */
|
||||
ravb_write(ndev, ~mask, TIS);
|
||||
ravb_tx_free(ndev, q);
|
||||
ravb_tx_free(ndev, q, true);
|
||||
netif_wake_subqueue(ndev, q);
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
@@ -1571,7 +1586,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
|
||||
priv->cur_tx[q] += NUM_TX_DESC;
|
||||
if (priv->cur_tx[q] - priv->dirty_tx[q] >
|
||||
(priv->num_tx_ring[q] - 1) * NUM_TX_DESC && !ravb_tx_free(ndev, q))
|
||||
(priv->num_tx_ring[q] - 1) * NUM_TX_DESC &&
|
||||
!ravb_tx_free(ndev, q, true))
|
||||
netif_stop_subqueue(ndev, q);
|
||||
|
||||
exit:
|
||||
|
||||
@@ -100,6 +100,14 @@
|
||||
/* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
|
||||
#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
#define xemaclite_readl ioread32be
|
||||
#define xemaclite_writel iowrite32be
|
||||
#else
|
||||
#define xemaclite_readl ioread32
|
||||
#define xemaclite_writel iowrite32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct net_local - Our private per device data
|
||||
* @ndev: instance of the network device
|
||||
@@ -156,15 +164,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
|
||||
u32 reg_data;
|
||||
|
||||
/* Enable the Tx interrupts for the first Buffer */
|
||||
reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
__raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
|
||||
drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
|
||||
drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
|
||||
/* Enable the Rx interrupts for the first buffer */
|
||||
__raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
|
||||
xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
|
||||
|
||||
/* Enable the Global Interrupt Enable */
|
||||
__raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
|
||||
xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,17 +187,17 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata)
|
||||
u32 reg_data;
|
||||
|
||||
/* Disable the Global Interrupt Enable */
|
||||
__raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
|
||||
xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
|
||||
|
||||
/* Disable the Tx interrupts for the first buffer */
|
||||
reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
__raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
|
||||
drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
|
||||
drvdata->base_addr + XEL_TSR_OFFSET);
|
||||
|
||||
/* Disable the Rx interrupts for the first buffer */
|
||||
reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
|
||||
__raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
|
||||
drvdata->base_addr + XEL_RSR_OFFSET);
|
||||
reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET);
|
||||
xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
|
||||
drvdata->base_addr + XEL_RSR_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,7 +329,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
||||
byte_count = ETH_FRAME_LEN;
|
||||
|
||||
/* Check if the expected buffer is available */
|
||||
reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
|
||||
reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
|
||||
if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
|
||||
XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
|
||||
|
||||
@@ -334,7 +342,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
||||
|
||||
addr = (void __iomem __force *)((u32 __force)addr ^
|
||||
XEL_BUFFER_OFFSET);
|
||||
reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
|
||||
reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
|
||||
|
||||
if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
|
||||
XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
|
||||
@@ -345,16 +353,16 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
||||
/* Write the frame to the buffer */
|
||||
xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
|
||||
|
||||
__raw_writel((byte_count & XEL_TPLR_LENGTH_MASK),
|
||||
addr + XEL_TPLR_OFFSET);
|
||||
xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK),
|
||||
addr + XEL_TPLR_OFFSET);
|
||||
|
||||
/* Update the Tx Status Register to indicate that there is a
|
||||
* frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
|
||||
* is used by the interrupt handler to check whether a frame
|
||||
* has been transmitted */
|
||||
reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
|
||||
reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
|
||||
reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
|
||||
__raw_writel(reg_data, addr + XEL_TSR_OFFSET);
|
||||
xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -369,7 +377,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
||||
*
|
||||
* Return: Total number of bytes received
|
||||
*/
|
||||
static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
|
||||
static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
|
||||
{
|
||||
void __iomem *addr;
|
||||
u16 length, proto_type;
|
||||
@@ -379,7 +387,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
|
||||
addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
|
||||
|
||||
/* Verify which buffer has valid data */
|
||||
reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
|
||||
reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
|
||||
|
||||
if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
|
||||
if (drvdata->rx_ping_pong != 0)
|
||||
@@ -396,27 +404,28 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
|
||||
return 0; /* No data was available */
|
||||
|
||||
/* Verify that buffer has valid data */
|
||||
reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
|
||||
reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
|
||||
if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
|
||||
XEL_RSR_RECV_DONE_MASK)
|
||||
return 0; /* No data was available */
|
||||
}
|
||||
|
||||
/* Get the protocol type of the ethernet frame that arrived */
|
||||
proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET +
|
||||
proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET +
|
||||
XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
|
||||
XEL_RPLR_LENGTH_MASK);
|
||||
|
||||
/* Check if received ethernet frame is a raw ethernet frame
|
||||
* or an IP packet or an ARP packet */
|
||||
if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
|
||||
if (proto_type > ETH_DATA_LEN) {
|
||||
|
||||
if (proto_type == ETH_P_IP) {
|
||||
length = ((ntohl(__raw_readl(addr +
|
||||
length = ((ntohl(xemaclite_readl(addr +
|
||||
XEL_HEADER_IP_LENGTH_OFFSET +
|
||||
XEL_RXBUFF_OFFSET)) >>
|
||||
XEL_HEADER_SHIFT) &
|
||||
XEL_RPLR_LENGTH_MASK);
|
||||
length = min_t(u16, length, ETH_DATA_LEN);
|
||||
length += ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
} else if (proto_type == ETH_P_ARP)
|
||||
@@ -429,14 +438,17 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
|
||||
/* Use the length in the frame, plus the header and trailer */
|
||||
length = proto_type + ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
if (WARN_ON(length > maxlen))
|
||||
length = maxlen;
|
||||
|
||||
/* Read from the EmacLite device */
|
||||
xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
|
||||
data, length);
|
||||
|
||||
/* Acknowledge the frame */
|
||||
reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
|
||||
reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
|
||||
reg_data &= ~XEL_RSR_RECV_DONE_MASK;
|
||||
__raw_writel(reg_data, addr + XEL_RSR_OFFSET);
|
||||
xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET);
|
||||
|
||||
return length;
|
||||
}
|
||||
@@ -463,14 +475,14 @@ static void xemaclite_update_address(struct net_local *drvdata,
|
||||
|
||||
xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
|
||||
|
||||
__raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
|
||||
xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
|
||||
|
||||
/* Update the MAC address in the EmacLite */
|
||||
reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
|
||||
__raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
|
||||
reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
|
||||
xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
|
||||
|
||||
/* Wait for EmacLite to finish with the MAC address update */
|
||||
while ((__raw_readl(addr + XEL_TSR_OFFSET) &
|
||||
while ((xemaclite_readl(addr + XEL_TSR_OFFSET) &
|
||||
XEL_TSR_PROG_MAC_ADDR) != 0)
|
||||
;
|
||||
}
|
||||
@@ -603,7 +615,7 @@ static void xemaclite_rx_handler(struct net_device *dev)
|
||||
|
||||
skb_reserve(skb, 2);
|
||||
|
||||
len = xemaclite_recv_data(lp, (u8 *) skb->data);
|
||||
len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
|
||||
|
||||
if (!len) {
|
||||
dev->stats.rx_errors++;
|
||||
@@ -640,32 +652,32 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
|
||||
u32 tx_status;
|
||||
|
||||
/* Check if there is Rx Data available */
|
||||
if ((__raw_readl(base_addr + XEL_RSR_OFFSET) &
|
||||
if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) &
|
||||
XEL_RSR_RECV_DONE_MASK) ||
|
||||
(__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
|
||||
(xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
|
||||
& XEL_RSR_RECV_DONE_MASK))
|
||||
|
||||
xemaclite_rx_handler(dev);
|
||||
|
||||
/* Check if the Transmission for the first buffer is completed */
|
||||
tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET);
|
||||
tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET);
|
||||
if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
|
||||
(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
|
||||
|
||||
tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
|
||||
__raw_writel(tx_status, base_addr + XEL_TSR_OFFSET);
|
||||
xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET);
|
||||
|
||||
tx_complete = true;
|
||||
}
|
||||
|
||||
/* Check if the Transmission for the second buffer is completed */
|
||||
tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
|
||||
tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
|
||||
if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
|
||||
(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
|
||||
|
||||
tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
|
||||
__raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
|
||||
XEL_TSR_OFFSET);
|
||||
xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
|
||||
XEL_TSR_OFFSET);
|
||||
|
||||
tx_complete = true;
|
||||
}
|
||||
@@ -698,7 +710,7 @@ static int xemaclite_mdio_wait(struct net_local *lp)
|
||||
/* wait for the MDIO interface to not be busy or timeout
|
||||
after some time.
|
||||
*/
|
||||
while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
|
||||
while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
|
||||
XEL_MDIOCTRL_MDIOSTS_MASK) {
|
||||
if (time_before_eq(end, jiffies)) {
|
||||
WARN_ON(1);
|
||||
@@ -734,17 +746,17 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
|
||||
* MDIO Address register. Set the Status bit in the MDIO Control
|
||||
* register to start a MDIO read transaction.
|
||||
*/
|
||||
ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
__raw_writel(XEL_MDIOADDR_OP_MASK |
|
||||
((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
|
||||
lp->base_addr + XEL_MDIOADDR_OFFSET);
|
||||
__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
|
||||
lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
xemaclite_writel(XEL_MDIOADDR_OP_MASK |
|
||||
((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
|
||||
lp->base_addr + XEL_MDIOADDR_OFFSET);
|
||||
xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
|
||||
lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
|
||||
if (xemaclite_mdio_wait(lp))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET);
|
||||
rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET);
|
||||
|
||||
dev_dbg(&lp->ndev->dev,
|
||||
"xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
|
||||
@@ -781,13 +793,13 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
|
||||
* Data register. Finally, set the Status bit in the MDIO Control
|
||||
* register to start a MDIO write transaction.
|
||||
*/
|
||||
ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
__raw_writel(~XEL_MDIOADDR_OP_MASK &
|
||||
((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
|
||||
lp->base_addr + XEL_MDIOADDR_OFFSET);
|
||||
__raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
|
||||
__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
|
||||
lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
xemaclite_writel(~XEL_MDIOADDR_OP_MASK &
|
||||
((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
|
||||
lp->base_addr + XEL_MDIOADDR_OFFSET);
|
||||
xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
|
||||
xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
|
||||
lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -834,8 +846,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
|
||||
/* Enable the MDIO bus by asserting the enable bit in MDIO Control
|
||||
* register.
|
||||
*/
|
||||
__raw_writel(XEL_MDIOCTRL_MDIOEN_MASK,
|
||||
lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK,
|
||||
lp->base_addr + XEL_MDIOCTRL_OFFSET);
|
||||
|
||||
bus = mdiobus_alloc();
|
||||
if (!bus) {
|
||||
@@ -1140,8 +1152,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
|
||||
}
|
||||
|
||||
/* Clear the Tx CSR's in case this is a restart */
|
||||
__raw_writel(0, lp->base_addr + XEL_TSR_OFFSET);
|
||||
__raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
|
||||
xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET);
|
||||
xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
|
||||
|
||||
/* Set the MAC address in the EmacLite device */
|
||||
xemaclite_update_address(lp, ndev->dev_addr);
|
||||
|
||||
@@ -1372,3 +1372,4 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Harald Welte <hwelte@sysmocom.de>");
|
||||
MODULE_DESCRIPTION("Interface driver for GTP encapsulated traffic");
|
||||
MODULE_ALIAS_RTNL_LINK("gtp");
|
||||
MODULE_ALIAS_GENL_FAMILY("gtp");
|
||||
|
||||
@@ -648,8 +648,8 @@ static void ax_setup(struct net_device *dev)
|
||||
{
|
||||
/* Finish setting up the DEVICE info. */
|
||||
dev->mtu = AX_MTU;
|
||||
dev->hard_header_len = 0;
|
||||
dev->addr_len = 0;
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN;
|
||||
dev->addr_len = AX25_ADDR_LEN;
|
||||
dev->type = ARPHRD_AX25;
|
||||
dev->tx_queue_len = 10;
|
||||
dev->header_ops = &ax25_header_ops;
|
||||
|
||||
@@ -1014,6 +1014,20 @@ static struct phy_driver ksphy_driver[] = {
|
||||
.get_stats = kszphy_get_stats,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
}, {
|
||||
.phy_id = PHY_ID_KSZ8795,
|
||||
.phy_id_mask = MICREL_PHY_ID_MASK,
|
||||
.name = "Micrel KSZ8795",
|
||||
.features = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
|
||||
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
|
||||
.config_init = kszphy_config_init,
|
||||
.config_aneg = ksz8873mll_config_aneg,
|
||||
.read_status = ksz8873mll_read_status,
|
||||
.get_sset_count = kszphy_get_sset_count,
|
||||
.get_strings = kszphy_get_strings,
|
||||
.get_stats = kszphy_get_stats,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
} };
|
||||
|
||||
module_phy_driver(ksphy_driver);
|
||||
|
||||
@@ -860,6 +860,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
struct module *ndev_owner = dev->dev.parent->driver->owner;
|
||||
struct mii_bus *bus = phydev->mdio.bus;
|
||||
struct device *d = &phydev->mdio.dev;
|
||||
bool using_genphy = false;
|
||||
int err;
|
||||
|
||||
/* For Ethernet device drivers that register their own MDIO bus, we
|
||||
@@ -885,12 +886,22 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
d->driver =
|
||||
&genphy_driver[GENPHY_DRV_1G].mdiodrv.driver;
|
||||
|
||||
using_genphy = true;
|
||||
}
|
||||
|
||||
if (!try_module_get(d->driver->owner)) {
|
||||
dev_err(&dev->dev, "failed to get the device driver module\n");
|
||||
err = -EIO;
|
||||
goto error_put_device;
|
||||
}
|
||||
|
||||
if (using_genphy) {
|
||||
err = d->driver->probe(d);
|
||||
if (err >= 0)
|
||||
err = device_bind_driver(d);
|
||||
|
||||
if (err)
|
||||
goto error;
|
||||
goto error_module_put;
|
||||
}
|
||||
|
||||
if (phydev->attached_dev) {
|
||||
@@ -926,6 +937,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
||||
return err;
|
||||
|
||||
error:
|
||||
/* phy_detach() does all of the cleanup below */
|
||||
phy_detach(phydev);
|
||||
return err;
|
||||
|
||||
error_module_put:
|
||||
module_put(d->driver->owner);
|
||||
error_put_device:
|
||||
put_device(d);
|
||||
if (ndev_owner != bus->owner)
|
||||
module_put(bus->owner);
|
||||
@@ -987,6 +1005,8 @@ void phy_detach(struct phy_device *phydev)
|
||||
phydev->attached_dev = NULL;
|
||||
phy_suspend(phydev);
|
||||
|
||||
module_put(phydev->mdio.dev.driver->owner);
|
||||
|
||||
/* If the device had no specific driver before (i.e. - it
|
||||
* was using the generic driver), we unbind the device
|
||||
* from the generic driver so that there's a chance a
|
||||
|
||||
+26
-6
@@ -32,7 +32,7 @@
|
||||
#define NETNEXT_VERSION "08"
|
||||
|
||||
/* Information for net */
|
||||
#define NET_VERSION "7"
|
||||
#define NET_VERSION "8"
|
||||
|
||||
#define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION
|
||||
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
|
||||
@@ -1936,6 +1936,9 @@ static int r8152_poll(struct napi_struct *napi, int budget)
|
||||
napi_complete(napi);
|
||||
if (!list_empty(&tp->rx_done))
|
||||
napi_schedule(napi);
|
||||
else if (!skb_queue_empty(&tp->tx_queue) &&
|
||||
!list_empty(&tp->tx_free))
|
||||
napi_schedule(napi);
|
||||
}
|
||||
|
||||
return work_done;
|
||||
@@ -3155,10 +3158,13 @@ static void set_carrier(struct r8152 *tp)
|
||||
if (!netif_carrier_ok(netdev)) {
|
||||
tp->rtl_ops.enable(tp);
|
||||
set_bit(RTL8152_SET_RX_MODE, &tp->flags);
|
||||
netif_stop_queue(netdev);
|
||||
napi_disable(&tp->napi);
|
||||
netif_carrier_on(netdev);
|
||||
rtl_start_rx(tp);
|
||||
napi_enable(&tp->napi);
|
||||
netif_wake_queue(netdev);
|
||||
netif_info(tp, link, netdev, "carrier on\n");
|
||||
}
|
||||
} else {
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
@@ -3166,6 +3172,7 @@ static void set_carrier(struct r8152 *tp)
|
||||
napi_disable(&tp->napi);
|
||||
tp->rtl_ops.disable(tp);
|
||||
napi_enable(&tp->napi);
|
||||
netif_info(tp, link, netdev, "carrier off\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3515,12 +3522,12 @@ static int rtl8152_pre_reset(struct usb_interface *intf)
|
||||
if (!netif_running(netdev))
|
||||
return 0;
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
napi_disable(&tp->napi);
|
||||
clear_bit(WORK_ENABLE, &tp->flags);
|
||||
usb_kill_urb(tp->intr_urb);
|
||||
cancel_delayed_work_sync(&tp->schedule);
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
netif_stop_queue(netdev);
|
||||
mutex_lock(&tp->control);
|
||||
tp->rtl_ops.disable(tp);
|
||||
mutex_unlock(&tp->control);
|
||||
@@ -3545,12 +3552,17 @@ static int rtl8152_post_reset(struct usb_interface *intf)
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
mutex_lock(&tp->control);
|
||||
tp->rtl_ops.enable(tp);
|
||||
rtl_start_rx(tp);
|
||||
rtl8152_set_rx_mode(netdev);
|
||||
mutex_unlock(&tp->control);
|
||||
netif_wake_queue(netdev);
|
||||
}
|
||||
|
||||
napi_enable(&tp->napi);
|
||||
netif_wake_queue(netdev);
|
||||
usb_submit_urb(tp->intr_urb, GFP_KERNEL);
|
||||
|
||||
if (!list_empty(&tp->rx_done))
|
||||
napi_schedule(&tp->napi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3583,10 +3595,15 @@ static int rtl8152_rumtime_suspend(struct r8152 *tp)
|
||||
struct net_device *netdev = tp->netdev;
|
||||
int ret = 0;
|
||||
|
||||
set_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
smp_mb__after_atomic();
|
||||
|
||||
if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
|
||||
u32 rcr = 0;
|
||||
|
||||
if (delay_autosuspend(tp)) {
|
||||
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
smp_mb__after_atomic();
|
||||
ret = -EBUSY;
|
||||
goto out1;
|
||||
}
|
||||
@@ -3603,6 +3620,8 @@ static int rtl8152_rumtime_suspend(struct r8152 *tp)
|
||||
if (!(ocp_data & RXFIFO_EMPTY)) {
|
||||
rxdy_gated_en(tp, false);
|
||||
ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
|
||||
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
smp_mb__after_atomic();
|
||||
ret = -EBUSY;
|
||||
goto out1;
|
||||
}
|
||||
@@ -3622,8 +3641,6 @@ static int rtl8152_rumtime_suspend(struct r8152 *tp)
|
||||
}
|
||||
}
|
||||
|
||||
set_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
@@ -3679,12 +3696,15 @@ static int rtl8152_resume(struct usb_interface *intf)
|
||||
if (netif_running(tp->netdev) && tp->netdev->flags & IFF_UP) {
|
||||
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
|
||||
tp->rtl_ops.autosuspend_en(tp, false);
|
||||
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
napi_disable(&tp->napi);
|
||||
set_bit(WORK_ENABLE, &tp->flags);
|
||||
if (netif_carrier_ok(tp->netdev))
|
||||
rtl_start_rx(tp);
|
||||
napi_enable(&tp->napi);
|
||||
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
smp_mb__after_atomic();
|
||||
if (!list_empty(&tp->rx_done))
|
||||
napi_schedule(&tp->napi);
|
||||
} else {
|
||||
tp->rtl_ops.up(tp);
|
||||
netif_carrier_off(tp->netdev);
|
||||
|
||||
@@ -73,8 +73,6 @@ static atomic_t iface_counter = ATOMIC_INIT(0);
|
||||
/* Private data structure */
|
||||
struct sierra_net_data {
|
||||
|
||||
u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */
|
||||
|
||||
u16 link_up; /* air link up or down */
|
||||
u8 tx_hdr_template[4]; /* part of HIP hdr for tx'd packets */
|
||||
|
||||
@@ -122,6 +120,7 @@ struct param {
|
||||
|
||||
/* LSI Protocol types */
|
||||
#define SIERRA_NET_PROTOCOL_UMTS 0x01
|
||||
#define SIERRA_NET_PROTOCOL_UMTS_DS 0x04
|
||||
/* LSI Coverage */
|
||||
#define SIERRA_NET_COVERAGE_NONE 0x00
|
||||
#define SIERRA_NET_COVERAGE_NOPACKET 0x01
|
||||
@@ -129,7 +128,8 @@ struct param {
|
||||
/* LSI Session */
|
||||
#define SIERRA_NET_SESSION_IDLE 0x00
|
||||
/* LSI Link types */
|
||||
#define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00
|
||||
#define SIERRA_NET_AS_LINK_TYPE_IPV4 0x00
|
||||
#define SIERRA_NET_AS_LINK_TYPE_IPV6 0x02
|
||||
|
||||
struct lsi_umts {
|
||||
u8 protocol;
|
||||
@@ -137,9 +137,14 @@ struct lsi_umts {
|
||||
__be16 length;
|
||||
/* eventually use a union for the rest - assume umts for now */
|
||||
u8 coverage;
|
||||
u8 unused2[41];
|
||||
u8 network_len; /* network name len */
|
||||
u8 network[40]; /* network name (UCS2, bigendian) */
|
||||
u8 session_state;
|
||||
u8 unused3[33];
|
||||
} __packed;
|
||||
|
||||
struct lsi_umts_single {
|
||||
struct lsi_umts lsi;
|
||||
u8 link_type;
|
||||
u8 pdp_addr_len; /* NW-supplied PDP address len */
|
||||
u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */
|
||||
@@ -158,10 +163,31 @@ struct lsi_umts {
|
||||
u8 reserved[8];
|
||||
} __packed;
|
||||
|
||||
struct lsi_umts_dual {
|
||||
struct lsi_umts lsi;
|
||||
u8 pdp_addr4_len; /* NW-supplied PDP IPv4 address len */
|
||||
u8 pdp_addr4[4]; /* NW-supplied PDP IPv4 address (bigendian)) */
|
||||
u8 pdp_addr6_len; /* NW-supplied PDP IPv6 address len */
|
||||
u8 pdp_addr6[16]; /* NW-supplied PDP IPv6 address (bigendian)) */
|
||||
u8 unused4[23];
|
||||
u8 dns1_addr4_len; /* NW-supplied 1st DNS v4 address len (bigendian) */
|
||||
u8 dns1_addr4[4]; /* NW-supplied 1st DNS v4 address */
|
||||
u8 dns1_addr6_len; /* NW-supplied 1st DNS v6 address len */
|
||||
u8 dns1_addr6[16]; /* NW-supplied 1st DNS v6 address (bigendian)*/
|
||||
u8 dns2_addr4_len; /* NW-supplied 2nd DNS v4 address len (bigendian) */
|
||||
u8 dns2_addr4[4]; /* NW-supplied 2nd DNS v4 address */
|
||||
u8 dns2_addr6_len; /* NW-supplied 2nd DNS v6 address len */
|
||||
u8 dns2_addr6[16]; /* NW-supplied 2nd DNS v6 address (bigendian)*/
|
||||
u8 unused5[68];
|
||||
} __packed;
|
||||
|
||||
#define SIERRA_NET_LSI_COMMON_LEN 4
|
||||
#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts))
|
||||
#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts_single))
|
||||
#define SIERRA_NET_LSI_UMTS_STATUS_LEN \
|
||||
(SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN)
|
||||
#define SIERRA_NET_LSI_UMTS_DS_LEN (sizeof(struct lsi_umts_dual))
|
||||
#define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \
|
||||
(SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN)
|
||||
|
||||
/* Forward definitions */
|
||||
static void sierra_sync_timer(unsigned long syncdata);
|
||||
@@ -191,10 +217,11 @@ static inline void sierra_net_set_private(struct usbnet *dev,
|
||||
dev->data[0] = (unsigned long)priv;
|
||||
}
|
||||
|
||||
/* is packet IPv4 */
|
||||
/* is packet IPv4/IPv6 */
|
||||
static inline int is_ip(struct sk_buff *skb)
|
||||
{
|
||||
return skb->protocol == cpu_to_be16(ETH_P_IP);
|
||||
return skb->protocol == cpu_to_be16(ETH_P_IP) ||
|
||||
skb->protocol == cpu_to_be16(ETH_P_IPV6);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -350,46 +377,51 @@ static inline int sierra_net_is_valid_addrlen(u8 len)
|
||||
static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
|
||||
{
|
||||
struct lsi_umts *lsi = (struct lsi_umts *)data;
|
||||
u32 expected_length;
|
||||
|
||||
if (datalen < sizeof(struct lsi_umts)) {
|
||||
netdev_err(dev->net, "%s: Data length %d, exp %Zu\n",
|
||||
__func__, datalen,
|
||||
sizeof(struct lsi_umts));
|
||||
if (datalen < sizeof(struct lsi_umts_single)) {
|
||||
netdev_err(dev->net, "%s: Data length %d, exp >= %Zu\n",
|
||||
__func__, datalen, sizeof(struct lsi_umts_single));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) {
|
||||
netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
|
||||
__func__, be16_to_cpu(lsi->length),
|
||||
(u32)SIERRA_NET_LSI_UMTS_STATUS_LEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Validate the protocol - only support UMTS for now */
|
||||
if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) {
|
||||
netdev_err(dev->net, "Protocol unsupported, 0x%02x\n",
|
||||
lsi->protocol);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Validate the link type */
|
||||
if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) {
|
||||
netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
|
||||
lsi->link_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Validate the coverage */
|
||||
if (lsi->coverage == SIERRA_NET_COVERAGE_NONE
|
||||
|| lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
|
||||
netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Validate the session state */
|
||||
if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
|
||||
netdev_err(dev->net, "Session idle, 0x%02x\n",
|
||||
lsi->session_state);
|
||||
lsi->session_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Validate the protocol - only support UMTS for now */
|
||||
if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS) {
|
||||
struct lsi_umts_single *single = (struct lsi_umts_single *)lsi;
|
||||
|
||||
/* Validate the link type */
|
||||
if (single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 &&
|
||||
single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV6) {
|
||||
netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
|
||||
single->link_type);
|
||||
return -1;
|
||||
}
|
||||
expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN;
|
||||
} else if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS_DS) {
|
||||
expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN;
|
||||
} else {
|
||||
netdev_err(dev->net, "Protocol unsupported, 0x%02x\n",
|
||||
lsi->protocol);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (be16_to_cpu(lsi->length) != expected_length) {
|
||||
netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
|
||||
__func__, be16_to_cpu(lsi->length), expected_length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Validate the coverage */
|
||||
if (lsi->coverage == SIERRA_NET_COVERAGE_NONE ||
|
||||
lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
|
||||
netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -662,7 +694,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
u8 numendpoints;
|
||||
u16 fwattr = 0;
|
||||
int status;
|
||||
struct ethhdr *eth;
|
||||
struct sierra_net_data *priv;
|
||||
static const u8 sync_tmplate[sizeof(priv->sync_msg)] = {
|
||||
0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00};
|
||||
@@ -700,11 +731,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
|
||||
dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
|
||||
|
||||
/* we will have to manufacture ethernet headers, prepare template */
|
||||
eth = (struct ethhdr *)priv->ethr_hdr_tmpl;
|
||||
memcpy(ð->h_dest, dev->net->dev_addr, ETH_ALEN);
|
||||
eth->h_proto = cpu_to_be16(ETH_P_IP);
|
||||
|
||||
/* prepare shutdown message template */
|
||||
memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg));
|
||||
/* set context index initially to 0 - prepares tx hdr template */
|
||||
@@ -833,9 +859,14 @@ static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
||||
|
||||
skb_pull(skb, hh.hdrlen);
|
||||
|
||||
/* We are going to accept this packet, prepare it */
|
||||
memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl,
|
||||
ETH_HLEN);
|
||||
/* We are going to accept this packet, prepare it.
|
||||
* In case protocol is IPv6, keep it, otherwise force IPv4.
|
||||
*/
|
||||
skb_reset_mac_header(skb);
|
||||
if (eth_hdr(skb)->h_proto != cpu_to_be16(ETH_P_IPV6))
|
||||
eth_hdr(skb)->h_proto = cpu_to_be16(ETH_P_IP);
|
||||
eth_zero_addr(eth_hdr(skb)->h_source);
|
||||
memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
|
||||
|
||||
/* Last packet in batch handled by usbnet */
|
||||
if (hh.payload_len.word == skb->len)
|
||||
|
||||
@@ -438,6 +438,10 @@ static int nvmet_rdma_post_recv(struct nvmet_rdma_device *ndev,
|
||||
{
|
||||
struct ib_recv_wr *bad_wr;
|
||||
|
||||
ib_dma_sync_single_for_device(ndev->device,
|
||||
cmd->sge[0].addr, cmd->sge[0].length,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
if (ndev->srq)
|
||||
return ib_post_srq_recv(ndev->srq, &cmd->wr, &bad_wr);
|
||||
return ib_post_recv(cmd->queue->cm_id->qp, &cmd->wr, &bad_wr);
|
||||
@@ -538,6 +542,11 @@ static void nvmet_rdma_queue_response(struct nvmet_req *req)
|
||||
first_wr = &rsp->send_wr;
|
||||
|
||||
nvmet_rdma_post_recv(rsp->queue->dev, rsp->cmd);
|
||||
|
||||
ib_dma_sync_single_for_device(rsp->queue->dev->device,
|
||||
rsp->send_sge.addr, rsp->send_sge.length,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (ib_post_send(cm_id->qp, first_wr, &bad_wr)) {
|
||||
pr_err("sending cmd response failed\n");
|
||||
nvmet_rdma_release_rsp(rsp);
|
||||
@@ -698,6 +707,14 @@ static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue,
|
||||
cmd->n_rdma = 0;
|
||||
cmd->req.port = queue->port;
|
||||
|
||||
|
||||
ib_dma_sync_single_for_cpu(queue->dev->device,
|
||||
cmd->cmd->sge[0].addr, cmd->cmd->sge[0].length,
|
||||
DMA_FROM_DEVICE);
|
||||
ib_dma_sync_single_for_cpu(queue->dev->device,
|
||||
cmd->send_sge.addr, cmd->send_sge.length,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (!nvmet_req_init(&cmd->req, &queue->nvme_cq,
|
||||
&queue->nvme_sq, &nvmet_rdma_ops))
|
||||
return;
|
||||
|
||||
@@ -293,7 +293,7 @@ struct parport *parport_gsc_probe_port(unsigned long base,
|
||||
p->irq = PARPORT_IRQ_NONE;
|
||||
}
|
||||
if (p->irq != PARPORT_IRQ_NONE) {
|
||||
printk(", irq %d", p->irq);
|
||||
pr_cont(", irq %d", p->irq);
|
||||
|
||||
if (p->dma == PARPORT_DMA_AUTO) {
|
||||
p->dma = PARPORT_DMA_NONE;
|
||||
@@ -303,8 +303,8 @@ struct parport *parport_gsc_probe_port(unsigned long base,
|
||||
is mandatory (see above) */
|
||||
p->dma = PARPORT_DMA_NONE;
|
||||
|
||||
printk(" [");
|
||||
#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
|
||||
pr_cont(" [");
|
||||
#define printmode(x) {if(p->modes&PARPORT_MODE_##x){pr_cont("%s%s",f?",":"",#x);f++;}}
|
||||
{
|
||||
int f = 0;
|
||||
printmode(PCSPP);
|
||||
@@ -315,7 +315,7 @@ struct parport *parport_gsc_probe_port(unsigned long base,
|
||||
// printmode(DMA);
|
||||
}
|
||||
#undef printmode
|
||||
printk("]\n");
|
||||
pr_cont("]\n");
|
||||
|
||||
if (p->irq != PARPORT_IRQ_NONE) {
|
||||
if (request_irq (p->irq, parport_irq_handler,
|
||||
|
||||
+2
-1
@@ -2142,7 +2142,8 @@ bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
|
||||
|
||||
if (!pm_runtime_suspended(dev)
|
||||
|| pci_target_state(pci_dev) != pci_dev->current_state
|
||||
|| platform_pci_need_resume(pci_dev))
|
||||
|| platform_pci_need_resume(pci_dev)
|
||||
|| (pci_dev->dev_flags & PCI_DEV_FLAGS_NEEDS_RESUME))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
||||
@@ -217,7 +217,7 @@ static const struct berlin_desc_group berlin4ct_soc_pinctrl_groups[] = {
|
||||
BERLIN_PINCTRL_GROUP("SCRD0_CRD_PRES", 0xc, 0x3, 0x15,
|
||||
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */
|
||||
BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* crd pres */
|
||||
BERLIN_PINCTRL_FUNCTION(0x1, "sd1a")), /* DAT3 */
|
||||
BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT3 */
|
||||
BERLIN_PINCTRL_GROUP("SPI1_SS0n", 0xc, 0x3, 0x18,
|
||||
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */
|
||||
BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO37 */
|
||||
|
||||
@@ -1250,10 +1250,12 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
|
||||
debounce = readl(db_reg);
|
||||
debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
|
||||
|
||||
if (arg)
|
||||
conf |= BYT_DEBOUNCE_EN;
|
||||
else
|
||||
conf &= ~BYT_DEBOUNCE_EN;
|
||||
|
||||
switch (arg) {
|
||||
case 0:
|
||||
conf &= BYT_DEBOUNCE_EN;
|
||||
break;
|
||||
case 375:
|
||||
debounce |= BYT_DEBOUNCE_PULSE_375US;
|
||||
break;
|
||||
@@ -1276,7 +1278,9 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
|
||||
debounce |= BYT_DEBOUNCE_PULSE_24MS;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
if (arg)
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
|
||||
@@ -1017,7 +1017,7 @@ static int cec_config_thread_func(void *arg)
|
||||
las->log_addr[i] = CEC_LOG_ADDR_INVALID;
|
||||
if (last_la == CEC_LOG_ADDR_INVALID ||
|
||||
last_la == CEC_LOG_ADDR_UNREGISTERED ||
|
||||
!(last_la & type2mask[type]))
|
||||
!((1 << last_la) & type2mask[type]))
|
||||
last_la = la_list[0];
|
||||
|
||||
err = cec_config_log_addr(adap, i, last_la);
|
||||
|
||||
@@ -1909,6 +1909,14 @@ static void musb_pm_runtime_check_session(struct musb *musb)
|
||||
static void musb_irq_work(struct work_struct *data)
|
||||
{
|
||||
struct musb *musb = container_of(data, struct musb, irq_work.work);
|
||||
int error;
|
||||
|
||||
error = pm_runtime_get_sync(musb->controller);
|
||||
if (error < 0) {
|
||||
dev_err(musb->controller, "Could not enable: %i\n", error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
musb_pm_runtime_check_session(musb);
|
||||
|
||||
@@ -1916,6 +1924,9 @@ static void musb_irq_work(struct work_struct *data)
|
||||
musb->xceiv_old_state = musb->xceiv->otg->state;
|
||||
sysfs_notify(&musb->controller->kobj, NULL, "mode");
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(musb->controller);
|
||||
pm_runtime_put_autosuspend(musb->controller);
|
||||
}
|
||||
|
||||
static void musb_recover_from_babble(struct musb *musb)
|
||||
|
||||
@@ -1246,6 +1246,8 @@ static void tce_iommu_release_ownership_ddw(struct tce_container *container,
|
||||
static long tce_iommu_take_ownership_ddw(struct tce_container *container,
|
||||
struct iommu_table_group *table_group)
|
||||
{
|
||||
long i, ret = 0;
|
||||
|
||||
if (!table_group->ops->create_table || !table_group->ops->set_window ||
|
||||
!table_group->ops->release_ownership) {
|
||||
WARN_ON_ONCE(1);
|
||||
@@ -1254,7 +1256,27 @@ static long tce_iommu_take_ownership_ddw(struct tce_container *container,
|
||||
|
||||
table_group->ops->take_ownership(table_group);
|
||||
|
||||
/* Set all windows to the new group */
|
||||
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
|
||||
struct iommu_table *tbl = container->tables[i];
|
||||
|
||||
if (!tbl)
|
||||
continue;
|
||||
|
||||
ret = table_group->ops->set_window(table_group, i, tbl);
|
||||
if (ret)
|
||||
goto release_exit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
release_exit:
|
||||
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i)
|
||||
table_group->ops->unset_window(table_group, i);
|
||||
|
||||
table_group->ops->release_ownership(table_group);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tce_iommu_attach_group(void *iommu_data,
|
||||
|
||||
@@ -368,6 +368,7 @@ static void vhost_vsock_handle_rx_kick(struct vhost_work *work)
|
||||
|
||||
static int vhost_vsock_start(struct vhost_vsock *vsock)
|
||||
{
|
||||
struct vhost_virtqueue *vq;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
@@ -378,19 +379,20 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
|
||||
struct vhost_virtqueue *vq = &vsock->vqs[i];
|
||||
vq = &vsock->vqs[i];
|
||||
|
||||
mutex_lock(&vq->mutex);
|
||||
|
||||
if (!vhost_vq_access_ok(vq)) {
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&vq->mutex);
|
||||
goto err_vq;
|
||||
}
|
||||
|
||||
if (!vq->private_data) {
|
||||
vq->private_data = vsock;
|
||||
vhost_vq_init_access(vq);
|
||||
ret = vhost_vq_init_access(vq);
|
||||
if (ret)
|
||||
goto err_vq;
|
||||
}
|
||||
|
||||
mutex_unlock(&vq->mutex);
|
||||
@@ -400,8 +402,11 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
|
||||
return 0;
|
||||
|
||||
err_vq:
|
||||
vq->private_data = NULL;
|
||||
mutex_unlock(&vq->mutex);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
|
||||
struct vhost_virtqueue *vq = &vsock->vqs[i];
|
||||
vq = &vsock->vqs[i];
|
||||
|
||||
mutex_lock(&vq->mutex);
|
||||
vq->private_data = NULL;
|
||||
|
||||
@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
|
||||
hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
|
||||
if (invalidate)
|
||||
set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
|
||||
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
|
||||
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
|
||||
}
|
||||
} else {
|
||||
@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
|
||||
wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
|
||||
/* Make sure any pending writes are cancelled. */
|
||||
if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
|
||||
fscache_invalidate_writes(cookie);
|
||||
|
||||
/* Reset the cookie state if it wasn't relinquished */
|
||||
if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
|
||||
atomic_inc(&cookie->n_active);
|
||||
|
||||
@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
|
||||
cookie->flags = 1 << FSCACHE_COOKIE_ENABLED;
|
||||
|
||||
spin_lock_init(&cookie->lock);
|
||||
spin_lock_init(&cookie->stores_lock);
|
||||
INIT_HLIST_HEAD(&cookie->backing_objects);
|
||||
|
||||
/* check the netfs type is not already present */
|
||||
|
||||
+30
-2
@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object
|
||||
static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
|
||||
static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
|
||||
static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
|
||||
static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);
|
||||
|
||||
#define __STATE_NAME(n) fscache_osm_##n
|
||||
#define STATE(n) (&__STATE_NAME(n))
|
||||
@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure);
|
||||
static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object);
|
||||
static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents);
|
||||
static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object);
|
||||
static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL);
|
||||
static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead);
|
||||
|
||||
static WAIT_STATE(WAIT_FOR_INIT, "?INI",
|
||||
TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
|
||||
@@ -229,6 +230,10 @@ execute_work_state:
|
||||
event = -1;
|
||||
if (new_state == NO_TRANSIT) {
|
||||
_debug("{OBJ%x} %s notrans", object->debug_id, state->name);
|
||||
if (unlikely(state == STATE(OBJECT_DEAD))) {
|
||||
_leave(" [dead]");
|
||||
return;
|
||||
}
|
||||
fscache_enqueue_object(object);
|
||||
event_mask = object->oob_event_mask;
|
||||
goto unmask_events;
|
||||
@@ -239,7 +244,7 @@ execute_work_state:
|
||||
object->state = state = new_state;
|
||||
|
||||
if (state->work) {
|
||||
if (unlikely(state->work == ((void *)2UL))) {
|
||||
if (unlikely(state == STATE(OBJECT_DEAD))) {
|
||||
_leave(" [dead]");
|
||||
return;
|
||||
}
|
||||
@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
|
||||
fscache_mark_object_dead(object);
|
||||
object->oob_event_mask = 0;
|
||||
|
||||
if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
|
||||
/* Reject any new read/write ops and abort any that are pending. */
|
||||
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
|
||||
fscache_cancel_all_ops(object);
|
||||
}
|
||||
|
||||
if (list_empty(&object->dependents) &&
|
||||
object->n_ops == 0 &&
|
||||
object->n_children == 0)
|
||||
@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object,
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(fscache_object_mark_killed);
|
||||
|
||||
/*
|
||||
* The object is dead. We can get here if an object gets queued by an event
|
||||
* that would lead to its death (such as EV_KILL) when the dispatcher is
|
||||
* already running (and so can be requeued) but hasn't yet cleared the event
|
||||
* mask.
|
||||
*/
|
||||
static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
|
||||
int event)
|
||||
{
|
||||
if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
|
||||
&object->flags))
|
||||
return NO_TRANSIT;
|
||||
|
||||
WARN(true, "FS-Cache object redispatched after death");
|
||||
return NO_TRANSIT;
|
||||
}
|
||||
|
||||
+17
-11
@@ -1425,26 +1425,32 @@ static struct shrinker glock_shrinker = {
|
||||
* @sdp: the filesystem
|
||||
* @bucket: the bucket
|
||||
*
|
||||
* Note that the function can be called multiple times on the same
|
||||
* object. So the user must ensure that the function can cope with
|
||||
* that.
|
||||
*/
|
||||
|
||||
static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
|
||||
{
|
||||
struct gfs2_glock *gl;
|
||||
struct rhash_head *pos;
|
||||
const struct bucket_table *tbl;
|
||||
int i;
|
||||
struct rhashtable_iter iter;
|
||||
|
||||
rcu_read_lock();
|
||||
tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
|
||||
for (i = 0; i < tbl->size; i++) {
|
||||
rht_for_each_entry_rcu(gl, pos, tbl, i, gl_node) {
|
||||
rhashtable_walk_enter(&gl_hash_table, &iter);
|
||||
|
||||
do {
|
||||
gl = ERR_PTR(rhashtable_walk_start(&iter));
|
||||
if (gl)
|
||||
continue;
|
||||
|
||||
while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl))
|
||||
if ((gl->gl_name.ln_sbd == sdp) &&
|
||||
lockref_get_not_dead(&gl->gl_lockref))
|
||||
examiner(gl);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
cond_resched();
|
||||
|
||||
rhashtable_walk_stop(&iter);
|
||||
} while (cond_resched(), gl == ERR_PTR(-EAGAIN));
|
||||
|
||||
rhashtable_walk_exit(&iter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1079,6 +1079,7 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
|
||||
case -NFS4ERR_BADXDR:
|
||||
case -NFS4ERR_RESOURCE:
|
||||
case -NFS4ERR_NOFILEHANDLE:
|
||||
case -NFS4ERR_MOVED:
|
||||
/* Non-seqid mutating errors */
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -3181,6 +3181,8 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
|
||||
iter.tgid += 1, iter = next_tgid(ns, iter)) {
|
||||
char name[PROC_NUMBUF];
|
||||
int len;
|
||||
|
||||
cond_resched();
|
||||
if (!has_pid_permissions(ns, iter.task, 2))
|
||||
continue;
|
||||
|
||||
|
||||
+22
-1
@@ -74,6 +74,7 @@
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/major.h>
|
||||
#include "internal.h"
|
||||
|
||||
static struct kmem_cache *romfs_inode_cachep;
|
||||
@@ -416,7 +417,22 @@ static void romfs_destroy_inode(struct inode *inode)
|
||||
static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
{
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
|
||||
u64 id = 0;
|
||||
|
||||
/* When calling huge_encode_dev(),
|
||||
* use sb->s_bdev->bd_dev when,
|
||||
* - CONFIG_ROMFS_ON_BLOCK defined
|
||||
* use sb->s_dev when,
|
||||
* - CONFIG_ROMFS_ON_BLOCK undefined and
|
||||
* - CONFIG_ROMFS_ON_MTD defined
|
||||
* leave id as 0 when,
|
||||
* - CONFIG_ROMFS_ON_BLOCK undefined and
|
||||
* - CONFIG_ROMFS_ON_MTD undefined
|
||||
*/
|
||||
if (sb->s_bdev)
|
||||
id = huge_encode_dev(sb->s_bdev->bd_dev);
|
||||
else if (sb->s_dev)
|
||||
id = huge_encode_dev(sb->s_dev);
|
||||
|
||||
buf->f_type = ROMFS_MAGIC;
|
||||
buf->f_namelen = ROMFS_MAXFN;
|
||||
@@ -489,6 +505,11 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_flags |= MS_RDONLY | MS_NOATIME;
|
||||
sb->s_op = &romfs_super_ops;
|
||||
|
||||
#ifdef CONFIG_ROMFS_ON_MTD
|
||||
/* Use same dev ID from the underlying mtdblock device */
|
||||
if (sb->s_mtd)
|
||||
sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);
|
||||
#endif
|
||||
/* read the image superblock and check it */
|
||||
rsb = kmalloc(512, GFP_KERNEL);
|
||||
if (!rsb)
|
||||
|
||||
+35
-2
@@ -63,6 +63,7 @@ struct userfaultfd_wait_queue {
|
||||
struct uffd_msg msg;
|
||||
wait_queue_t wq;
|
||||
struct userfaultfd_ctx *ctx;
|
||||
bool waken;
|
||||
};
|
||||
|
||||
struct userfaultfd_wake_range {
|
||||
@@ -86,6 +87,12 @@ static int userfaultfd_wake_function(wait_queue_t *wq, unsigned mode,
|
||||
if (len && (start > uwq->msg.arg.pagefault.address ||
|
||||
start + len <= uwq->msg.arg.pagefault.address))
|
||||
goto out;
|
||||
WRITE_ONCE(uwq->waken, true);
|
||||
/*
|
||||
* The implicit smp_mb__before_spinlock in try_to_wake_up()
|
||||
* renders uwq->waken visible to other CPUs before the task is
|
||||
* waken.
|
||||
*/
|
||||
ret = wake_up_state(wq->private, mode);
|
||||
if (ret)
|
||||
/*
|
||||
@@ -264,6 +271,7 @@ int handle_userfault(struct fault_env *fe, unsigned long reason)
|
||||
struct userfaultfd_wait_queue uwq;
|
||||
int ret;
|
||||
bool must_wait, return_to_userland;
|
||||
long blocking_state;
|
||||
|
||||
BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
|
||||
|
||||
@@ -333,10 +341,13 @@ int handle_userfault(struct fault_env *fe, unsigned long reason)
|
||||
uwq.wq.private = current;
|
||||
uwq.msg = userfault_msg(fe->address, fe->flags, reason);
|
||||
uwq.ctx = ctx;
|
||||
uwq.waken = false;
|
||||
|
||||
return_to_userland =
|
||||
(fe->flags & (FAULT_FLAG_USER|FAULT_FLAG_KILLABLE)) ==
|
||||
(FAULT_FLAG_USER|FAULT_FLAG_KILLABLE);
|
||||
blocking_state = return_to_userland ? TASK_INTERRUPTIBLE :
|
||||
TASK_KILLABLE;
|
||||
|
||||
spin_lock(&ctx->fault_pending_wqh.lock);
|
||||
/*
|
||||
@@ -349,8 +360,7 @@ int handle_userfault(struct fault_env *fe, unsigned long reason)
|
||||
* following the spin_unlock to happen before the list_add in
|
||||
* __add_wait_queue.
|
||||
*/
|
||||
set_current_state(return_to_userland ? TASK_INTERRUPTIBLE :
|
||||
TASK_KILLABLE);
|
||||
set_current_state(blocking_state);
|
||||
spin_unlock(&ctx->fault_pending_wqh.lock);
|
||||
|
||||
must_wait = userfaultfd_must_wait(ctx, fe->address, fe->flags, reason);
|
||||
@@ -362,6 +372,29 @@ int handle_userfault(struct fault_env *fe, unsigned long reason)
|
||||
wake_up_poll(&ctx->fd_wqh, POLLIN);
|
||||
schedule();
|
||||
ret |= VM_FAULT_MAJOR;
|
||||
|
||||
/*
|
||||
* False wakeups can orginate even from rwsem before
|
||||
* up_read() however userfaults will wait either for a
|
||||
* targeted wakeup on the specific uwq waitqueue from
|
||||
* wake_userfault() or for signals or for uffd
|
||||
* release.
|
||||
*/
|
||||
while (!READ_ONCE(uwq.waken)) {
|
||||
/*
|
||||
* This needs the full smp_store_mb()
|
||||
* guarantee as the state write must be
|
||||
* visible to other CPUs before reading
|
||||
* uwq.waken from other CPUs.
|
||||
*/
|
||||
set_current_state(blocking_state);
|
||||
if (READ_ONCE(uwq.waken) ||
|
||||
READ_ONCE(ctx->released) ||
|
||||
(return_to_userland ? signal_pending(current) :
|
||||
fatal_signal_pending(current)))
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
@@ -776,6 +776,7 @@ struct drm_device {
|
||||
struct drm_minor *control; /**< Control node */
|
||||
struct drm_minor *primary; /**< Primary node */
|
||||
struct drm_minor *render; /**< Render node */
|
||||
bool registered;
|
||||
|
||||
/* currently active master for this device. Protected by master_mutex */
|
||||
struct drm_master *master;
|
||||
|
||||
@@ -345,6 +345,8 @@ struct drm_connector_funcs {
|
||||
* core drm connector interfaces. Everything added from this callback
|
||||
* should be unregistered in the early_unregister callback.
|
||||
*
|
||||
* This is called while holding drm_connector->mutex.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, or a negative error code on failure.
|
||||
@@ -359,6 +361,8 @@ struct drm_connector_funcs {
|
||||
* late_register(). It is called from drm_connector_unregister(),
|
||||
* early in the driver unload sequence to disable userspace access
|
||||
* before data structures are torndown.
|
||||
*
|
||||
* This is called while holding drm_connector->mutex.
|
||||
*/
|
||||
void (*early_unregister)(struct drm_connector *connector);
|
||||
|
||||
@@ -511,7 +515,6 @@ struct drm_cmdline_mode {
|
||||
* @interlace_allowed: can this connector handle interlaced modes?
|
||||
* @doublescan_allowed: can this connector handle doublescan?
|
||||
* @stereo_allowed: can this connector handle stereo modes?
|
||||
* @registered: is this connector exposed (registered) with userspace?
|
||||
* @modes: modes available on this connector (from fill_modes() + user)
|
||||
* @status: one of the drm_connector_status enums (connected, not, or unknown)
|
||||
* @probed_modes: list of modes derived directly from the display
|
||||
@@ -559,6 +562,13 @@ struct drm_connector {
|
||||
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* @mutex: Lock for general connector state, but currently only protects
|
||||
* @registered. Most of the connector state is still protected by the
|
||||
* mutex in &drm_mode_config.
|
||||
*/
|
||||
struct mutex mutex;
|
||||
|
||||
/**
|
||||
* @index: Compacted connector index, which matches the position inside
|
||||
* the mode_config.list for drivers not supporting hot-add/removing. Can
|
||||
@@ -572,6 +582,10 @@ struct drm_connector {
|
||||
bool interlace_allowed;
|
||||
bool doublescan_allowed;
|
||||
bool stereo_allowed;
|
||||
/**
|
||||
* @registered: Is this connector exposed (registered) with userspace?
|
||||
* Protected by @mutex.
|
||||
*/
|
||||
bool registered;
|
||||
struct list_head modes; /* list of modes on this connector */
|
||||
|
||||
|
||||
@@ -360,6 +360,7 @@ struct fscache_object {
|
||||
#define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */
|
||||
#define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */
|
||||
#define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */
|
||||
#define FSCACHE_OBJECT_RUN_AFTER_DEAD 8 /* T if object has been dispatched after death */
|
||||
|
||||
struct list_head cache_link; /* link in cache->object_list */
|
||||
struct hlist_node cookie_link; /* link in cookie->backing_objects */
|
||||
|
||||
+12
-1
@@ -194,6 +194,17 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
|
||||
* ... and so on.
|
||||
*/
|
||||
|
||||
#define order_base_2(n) ilog2(roundup_pow_of_two(n))
|
||||
static inline __attribute_const__
|
||||
int __order_base_2(unsigned long n)
|
||||
{
|
||||
return n > 1 ? ilog2(n - 1) + 1 : 0;
|
||||
}
|
||||
|
||||
#define order_base_2(n) \
|
||||
( \
|
||||
__builtin_constant_p(n) ? ( \
|
||||
((n) == 0 || (n) == 1) ? 0 : \
|
||||
ilog2((n) - 1) + 1) : \
|
||||
__order_base_2(n) \
|
||||
)
|
||||
#endif /* _LINUX_LOG2_H */
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#define PHY_ID_KSZ886X 0x00221430
|
||||
#define PHY_ID_KSZ8863 0x00221435
|
||||
|
||||
#define PHY_ID_KSZ8795 0x00221550
|
||||
|
||||
/* struct phy_device dev_flags definitions */
|
||||
#define MICREL_PHY_50MHZ_CLK 0x00000001
|
||||
#define MICREL_PHY_FXEN 0x00000002
|
||||
|
||||
+15
-14
@@ -865,11 +865,15 @@ struct netdev_xdp {
|
||||
* of useless work if you return NETDEV_TX_BUSY.
|
||||
* Required; cannot be NULL.
|
||||
*
|
||||
* netdev_features_t (*ndo_fix_features)(struct net_device *dev,
|
||||
* netdev_features_t features);
|
||||
* Adjusts the requested feature flags according to device-specific
|
||||
* constraints, and returns the resulting flags. Must not modify
|
||||
* the device state.
|
||||
* netdev_features_t (*ndo_features_check)(struct sk_buff *skb,
|
||||
* struct net_device *dev
|
||||
* netdev_features_t features);
|
||||
* Called by core transmit path to determine if device is capable of
|
||||
* performing offload operations on a given packet. This is to give
|
||||
* the device an opportunity to implement any restrictions that cannot
|
||||
* be otherwise expressed by feature flags. The check is called with
|
||||
* the set of features that the stack has calculated and it returns
|
||||
* those the driver believes to be appropriate.
|
||||
*
|
||||
* u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
|
||||
* void *accel_priv, select_queue_fallback_t fallback);
|
||||
@@ -1027,6 +1031,12 @@ struct netdev_xdp {
|
||||
* Called to release previously enslaved netdev.
|
||||
*
|
||||
* Feature/offload setting functions.
|
||||
* netdev_features_t (*ndo_fix_features)(struct net_device *dev,
|
||||
* netdev_features_t features);
|
||||
* Adjusts the requested feature flags according to device-specific
|
||||
* constraints, and returns the resulting flags. Must not modify
|
||||
* the device state.
|
||||
*
|
||||
* int (*ndo_set_features)(struct net_device *dev, netdev_features_t features);
|
||||
* Called to update device configuration to new features. Passed
|
||||
* feature set might be less than what was returned by ndo_fix_features()).
|
||||
@@ -1099,15 +1109,6 @@ struct netdev_xdp {
|
||||
* Callback to use for xmit over the accelerated station. This
|
||||
* is used in place of ndo_start_xmit on accelerated net
|
||||
* devices.
|
||||
* netdev_features_t (*ndo_features_check)(struct sk_buff *skb,
|
||||
* struct net_device *dev
|
||||
* netdev_features_t features);
|
||||
* Called by core transmit path to determine if device is capable of
|
||||
* performing offload operations on a given packet. This is to give
|
||||
* the device an opportunity to implement any restrictions that cannot
|
||||
* be otherwise expressed by feature flags. The check is called with
|
||||
* the set of features that the stack has calculated and it returns
|
||||
* those the driver believes to be appropriate.
|
||||
* int (*ndo_set_tx_maxrate)(struct net_device *dev,
|
||||
* int queue_index, u32 maxrate);
|
||||
* Called when a user wants to set a max-rate limitation of specific
|
||||
|
||||
@@ -7,6 +7,23 @@
|
||||
#include <linux/sched.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/*
|
||||
* The run state of the lockup detectors is controlled by the content of the
|
||||
* 'watchdog_enabled' variable. Each lockup detector has its dedicated bit -
|
||||
* bit 0 for the hard lockup detector and bit 1 for the soft lockup detector.
|
||||
*
|
||||
* 'watchdog_user_enabled', 'nmi_watchdog_enabled' and 'soft_watchdog_enabled'
|
||||
* are variables that are only used as an 'interface' between the parameters
|
||||
* in /proc/sys/kernel and the internal state bits in 'watchdog_enabled'. The
|
||||
* 'watchdog_thresh' variable is handled differently because its value is not
|
||||
* boolean, and the lockup detectors are 'suspended' while 'watchdog_thresh'
|
||||
* is equal zero.
|
||||
*/
|
||||
#define NMI_WATCHDOG_ENABLED_BIT 0
|
||||
#define SOFT_WATCHDOG_ENABLED_BIT 1
|
||||
#define NMI_WATCHDOG_ENABLED (1 << NMI_WATCHDOG_ENABLED_BIT)
|
||||
#define SOFT_WATCHDOG_ENABLED (1 << SOFT_WATCHDOG_ENABLED_BIT)
|
||||
|
||||
/**
|
||||
* touch_nmi_watchdog - restart NMI watchdog timeout.
|
||||
*
|
||||
@@ -91,9 +108,17 @@ extern int nmi_watchdog_enabled;
|
||||
extern int soft_watchdog_enabled;
|
||||
extern int watchdog_user_enabled;
|
||||
extern int watchdog_thresh;
|
||||
extern unsigned long watchdog_enabled;
|
||||
extern unsigned long *watchdog_cpumask_bits;
|
||||
extern atomic_t watchdog_park_in_progress;
|
||||
#ifdef CONFIG_SMP
|
||||
extern int sysctl_softlockup_all_cpu_backtrace;
|
||||
extern int sysctl_hardlockup_all_cpu_backtrace;
|
||||
#else
|
||||
#define sysctl_softlockup_all_cpu_backtrace 0
|
||||
#define sysctl_hardlockup_all_cpu_backtrace 0
|
||||
#endif
|
||||
extern bool is_hardlockup(void);
|
||||
struct ctl_table;
|
||||
extern int proc_watchdog(struct ctl_table *, int ,
|
||||
void __user *, size_t *, loff_t *);
|
||||
|
||||
@@ -178,6 +178,11 @@ enum pci_dev_flags {
|
||||
PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
|
||||
/* Get VPD from function 0 VPD */
|
||||
PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
|
||||
/*
|
||||
* Resume before calling the driver's system suspend hooks, disabling
|
||||
* the direct_complete optimization.
|
||||
*/
|
||||
PCI_DEV_FLAGS_NEEDS_RESUME = (__force pci_dev_flags_t) (1 << 11),
|
||||
};
|
||||
|
||||
enum pci_irq_reroute_variant {
|
||||
|
||||
@@ -776,6 +776,11 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
|
||||
{
|
||||
u32 hash;
|
||||
|
||||
/* @flowlabel may include more than a flow label, eg, the traffic class.
|
||||
* Here we want only the flow label value.
|
||||
*/
|
||||
flowlabel &= IPV6_FLOWLABEL_MASK;
|
||||
|
||||
if (flowlabel ||
|
||||
net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF ||
|
||||
(!autolabel &&
|
||||
|
||||
@@ -9,4 +9,6 @@
|
||||
#define NF_LOG_MACDECODE 0x20 /* Decode MAC header */
|
||||
#define NF_LOG_MASK 0x2f
|
||||
|
||||
#define NF_LOG_PREFIXLEN 128
|
||||
|
||||
#endif /* _NETFILTER_NF_LOG_H */
|
||||
|
||||
@@ -84,6 +84,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
obj-$(CONFIG_KGDB) += debug/
|
||||
obj-$(CONFIG_DETECT_HUNG_TASK) += hung_task.o
|
||||
obj-$(CONFIG_LOCKUP_DETECTOR) += watchdog.o
|
||||
obj-$(CONFIG_HARDLOCKUP_DETECTOR) += watchdog_hld.o
|
||||
obj-$(CONFIG_SECCOMP) += seccomp.o
|
||||
obj-$(CONFIG_RELAY) += relay.o
|
||||
obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
|
||||
|
||||
+1
-2
@@ -231,11 +231,10 @@ static __init int user_namespace_sysctl_init(void)
|
||||
* properly.
|
||||
*/
|
||||
user_header = register_sysctl("user", empty);
|
||||
kmemleak_ignore(user_header);
|
||||
BUG_ON(!user_header);
|
||||
BUG_ON(!setup_userns_sysctls(&init_user_ns));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(user_namespace_sysctl_init);
|
||||
|
||||
|
||||
|
||||
+24
-254
@@ -24,32 +24,14 @@
|
||||
|
||||
#include <asm/irq_regs.h>
|
||||
#include <linux/kvm_para.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
/*
|
||||
* The run state of the lockup detectors is controlled by the content of the
|
||||
* 'watchdog_enabled' variable. Each lockup detector has its dedicated bit -
|
||||
* bit 0 for the hard lockup detector and bit 1 for the soft lockup detector.
|
||||
*
|
||||
* 'watchdog_user_enabled', 'nmi_watchdog_enabled' and 'soft_watchdog_enabled'
|
||||
* are variables that are only used as an 'interface' between the parameters
|
||||
* in /proc/sys/kernel and the internal state bits in 'watchdog_enabled'. The
|
||||
* 'watchdog_thresh' variable is handled differently because its value is not
|
||||
* boolean, and the lockup detectors are 'suspended' while 'watchdog_thresh'
|
||||
* is equal zero.
|
||||
*/
|
||||
#define NMI_WATCHDOG_ENABLED_BIT 0
|
||||
#define SOFT_WATCHDOG_ENABLED_BIT 1
|
||||
#define NMI_WATCHDOG_ENABLED (1 << NMI_WATCHDOG_ENABLED_BIT)
|
||||
#define SOFT_WATCHDOG_ENABLED (1 << SOFT_WATCHDOG_ENABLED_BIT)
|
||||
|
||||
static DEFINE_MUTEX(watchdog_proc_mutex);
|
||||
|
||||
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
||||
static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED|NMI_WATCHDOG_ENABLED;
|
||||
#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
|
||||
unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED|NMI_WATCHDOG_ENABLED;
|
||||
#else
|
||||
static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED;
|
||||
unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED;
|
||||
#endif
|
||||
int __read_mostly nmi_watchdog_enabled;
|
||||
int __read_mostly soft_watchdog_enabled;
|
||||
@@ -59,9 +41,6 @@ int __read_mostly watchdog_thresh = 10;
|
||||
#ifdef CONFIG_SMP
|
||||
int __read_mostly sysctl_softlockup_all_cpu_backtrace;
|
||||
int __read_mostly sysctl_hardlockup_all_cpu_backtrace;
|
||||
#else
|
||||
#define sysctl_softlockup_all_cpu_backtrace 0
|
||||
#define sysctl_hardlockup_all_cpu_backtrace 0
|
||||
#endif
|
||||
static struct cpumask watchdog_cpumask __read_mostly;
|
||||
unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
|
||||
@@ -70,6 +49,8 @@ unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
|
||||
#define for_each_watchdog_cpu(cpu) \
|
||||
for_each_cpu_and((cpu), cpu_online_mask, &watchdog_cpumask)
|
||||
|
||||
atomic_t watchdog_park_in_progress = ATOMIC_INIT(0);
|
||||
|
||||
/*
|
||||
* The 'watchdog_running' variable is set to 1 when the watchdog threads
|
||||
* are registered/started and is set to 0 when the watchdog threads are
|
||||
@@ -100,50 +81,9 @@ static DEFINE_PER_CPU(bool, soft_watchdog_warn);
|
||||
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
|
||||
static DEFINE_PER_CPU(unsigned long, soft_lockup_hrtimer_cnt);
|
||||
static DEFINE_PER_CPU(struct task_struct *, softlockup_task_ptr_saved);
|
||||
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
||||
static DEFINE_PER_CPU(bool, hard_watchdog_warn);
|
||||
static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
|
||||
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
|
||||
static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
|
||||
#endif
|
||||
static unsigned long soft_lockup_nmi_warn;
|
||||
|
||||
/* boot commands */
|
||||
/*
|
||||
* Should we panic when a soft-lockup or hard-lockup occurs:
|
||||
*/
|
||||
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
||||
unsigned int __read_mostly hardlockup_panic =
|
||||
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
|
||||
static unsigned long hardlockup_allcpu_dumped;
|
||||
/*
|
||||
* We may not want to enable hard lockup detection by default in all cases,
|
||||
* for example when running the kernel as a guest on a hypervisor. In these
|
||||
* cases this function can be called to disable hard lockup detection. This
|
||||
* function should only be executed once by the boot processor before the
|
||||
* kernel command line parameters are parsed, because otherwise it is not
|
||||
* possible to override this in hardlockup_panic_setup().
|
||||
*/
|
||||
void hardlockup_detector_disable(void)
|
||||
{
|
||||
watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
|
||||
}
|
||||
|
||||
static int __init hardlockup_panic_setup(char *str)
|
||||
{
|
||||
if (!strncmp(str, "panic", 5))
|
||||
hardlockup_panic = 1;
|
||||
else if (!strncmp(str, "nopanic", 7))
|
||||
hardlockup_panic = 0;
|
||||
else if (!strncmp(str, "0", 1))
|
||||
watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
|
||||
else if (!strncmp(str, "1", 1))
|
||||
watchdog_enabled |= NMI_WATCHDOG_ENABLED;
|
||||
return 1;
|
||||
}
|
||||
__setup("nmi_watchdog=", hardlockup_panic_setup);
|
||||
#endif
|
||||
|
||||
unsigned int __read_mostly softlockup_panic =
|
||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
|
||||
|
||||
@@ -264,32 +204,14 @@ void touch_all_softlockup_watchdogs(void)
|
||||
wq_watchdog_touch(-1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
||||
void touch_nmi_watchdog(void)
|
||||
{
|
||||
/*
|
||||
* Using __raw here because some code paths have
|
||||
* preemption enabled. If preemption is enabled
|
||||
* then interrupts should be enabled too, in which
|
||||
* case we shouldn't have to worry about the watchdog
|
||||
* going off.
|
||||
*/
|
||||
raw_cpu_write(watchdog_nmi_touch, true);
|
||||
touch_softlockup_watchdog();
|
||||
}
|
||||
EXPORT_SYMBOL(touch_nmi_watchdog);
|
||||
|
||||
#endif
|
||||
|
||||
void touch_softlockup_watchdog_sync(void)
|
||||
{
|
||||
__this_cpu_write(softlockup_touch_sync, true);
|
||||
__this_cpu_write(watchdog_touch_ts, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
||||
/* watchdog detector functions */
|
||||
static bool is_hardlockup(void)
|
||||
bool is_hardlockup(void)
|
||||
{
|
||||
unsigned long hrint = __this_cpu_read(hrtimer_interrupts);
|
||||
|
||||
@@ -299,7 +221,6 @@ static bool is_hardlockup(void)
|
||||
__this_cpu_write(hrtimer_interrupts_saved, hrint);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int is_softlockup(unsigned long touch_ts)
|
||||
{
|
||||
@@ -313,77 +234,22 @@ static int is_softlockup(unsigned long touch_ts)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
||||
|
||||
static struct perf_event_attr wd_hw_attr = {
|
||||
.type = PERF_TYPE_HARDWARE,
|
||||
.config = PERF_COUNT_HW_CPU_CYCLES,
|
||||
.size = sizeof(struct perf_event_attr),
|
||||
.pinned = 1,
|
||||
.disabled = 1,
|
||||
};
|
||||
|
||||
/* Callback function for perf event subsystem */
|
||||
static void watchdog_overflow_callback(struct perf_event *event,
|
||||
struct perf_sample_data *data,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
/* Ensure the watchdog never gets throttled */
|
||||
event->hw.interrupts = 0;
|
||||
|
||||
if (__this_cpu_read(watchdog_nmi_touch) == true) {
|
||||
__this_cpu_write(watchdog_nmi_touch, false);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for a hardlockup
|
||||
* This is done by making sure our timer interrupt
|
||||
* is incrementing. The timer interrupt should have
|
||||
* fired multiple times before we overflow'd. If it hasn't
|
||||
* then this is a good indication the cpu is stuck
|
||||
*/
|
||||
if (is_hardlockup()) {
|
||||
int this_cpu = smp_processor_id();
|
||||
|
||||
/* only print hardlockups once */
|
||||
if (__this_cpu_read(hard_watchdog_warn) == true)
|
||||
return;
|
||||
|
||||
pr_emerg("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
|
||||
print_modules();
|
||||
print_irqtrace_events(current);
|
||||
if (regs)
|
||||
show_regs(regs);
|
||||
else
|
||||
dump_stack();
|
||||
|
||||
/*
|
||||
* Perform all-CPU dump only once to avoid multiple hardlockups
|
||||
* generating interleaving traces
|
||||
*/
|
||||
if (sysctl_hardlockup_all_cpu_backtrace &&
|
||||
!test_and_set_bit(0, &hardlockup_allcpu_dumped))
|
||||
trigger_allbutself_cpu_backtrace();
|
||||
|
||||
if (hardlockup_panic)
|
||||
nmi_panic(regs, "Hard LOCKUP");
|
||||
|
||||
__this_cpu_write(hard_watchdog_warn, true);
|
||||
return;
|
||||
}
|
||||
|
||||
__this_cpu_write(hard_watchdog_warn, false);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_HARDLOCKUP_DETECTOR */
|
||||
|
||||
static void watchdog_interrupt_count(void)
|
||||
{
|
||||
__this_cpu_inc(hrtimer_interrupts);
|
||||
}
|
||||
|
||||
static int watchdog_nmi_enable(unsigned int cpu);
|
||||
static void watchdog_nmi_disable(unsigned int cpu);
|
||||
/*
|
||||
* These two functions are mostly architecture specific
|
||||
* defining them as weak here.
|
||||
*/
|
||||
int __weak watchdog_nmi_enable(unsigned int cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void __weak watchdog_nmi_disable(unsigned int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static int watchdog_enable_all_cpus(void);
|
||||
static void watchdog_disable_all_cpus(void);
|
||||
@@ -396,6 +262,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
||||
int duration;
|
||||
int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
|
||||
|
||||
if (atomic_read(&watchdog_park_in_progress) != 0)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
/* kick the hardlockup detector */
|
||||
watchdog_interrupt_count();
|
||||
|
||||
@@ -576,109 +445,6 @@ static void watchdog(unsigned int cpu)
|
||||
watchdog_nmi_disable(cpu);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
||||
/*
|
||||
* People like the simple clean cpu node info on boot.
|
||||
* Reduce the watchdog noise by only printing messages
|
||||
* that are different from what cpu0 displayed.
|
||||
*/
|
||||
static unsigned long cpu0_err;
|
||||
|
||||
static int watchdog_nmi_enable(unsigned int cpu)
|
||||
{
|
||||
struct perf_event_attr *wd_attr;
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
|
||||
/* nothing to do if the hard lockup detector is disabled */
|
||||
if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
|
||||
goto out;
|
||||
|
||||
/* is it already setup and enabled? */
|
||||
if (event && event->state > PERF_EVENT_STATE_OFF)
|
||||
goto out;
|
||||
|
||||
/* it is setup but not enabled */
|
||||
if (event != NULL)
|
||||
goto out_enable;
|
||||
|
||||
wd_attr = &wd_hw_attr;
|
||||
wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
|
||||
|
||||
/* Try to register using hardware perf events */
|
||||
event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
|
||||
|
||||
/* save cpu0 error for future comparision */
|
||||
if (cpu == 0 && IS_ERR(event))
|
||||
cpu0_err = PTR_ERR(event);
|
||||
|
||||
if (!IS_ERR(event)) {
|
||||
/* only print for cpu0 or different than cpu0 */
|
||||
if (cpu == 0 || cpu0_err)
|
||||
pr_info("enabled on all CPUs, permanently consumes one hw-PMU counter.\n");
|
||||
goto out_save;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the hard lockup detector if _any_ CPU fails to set up
|
||||
* set up the hardware perf event. The watchdog() function checks
|
||||
* the NMI_WATCHDOG_ENABLED bit periodically.
|
||||
*
|
||||
* The barriers are for syncing up watchdog_enabled across all the
|
||||
* cpus, as clear_bit() does not use barriers.
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(NMI_WATCHDOG_ENABLED_BIT, &watchdog_enabled);
|
||||
smp_mb__after_atomic();
|
||||
|
||||
/* skip displaying the same error again */
|
||||
if (cpu > 0 && (PTR_ERR(event) == cpu0_err))
|
||||
return PTR_ERR(event);
|
||||
|
||||
/* vary the KERN level based on the returned errno */
|
||||
if (PTR_ERR(event) == -EOPNOTSUPP)
|
||||
pr_info("disabled (cpu%i): not supported (no LAPIC?)\n", cpu);
|
||||
else if (PTR_ERR(event) == -ENOENT)
|
||||
pr_warn("disabled (cpu%i): hardware events not enabled\n",
|
||||
cpu);
|
||||
else
|
||||
pr_err("disabled (cpu%i): unable to create perf event: %ld\n",
|
||||
cpu, PTR_ERR(event));
|
||||
|
||||
pr_info("Shutting down hard lockup detector on all cpus\n");
|
||||
|
||||
return PTR_ERR(event);
|
||||
|
||||
/* success path */
|
||||
out_save:
|
||||
per_cpu(watchdog_ev, cpu) = event;
|
||||
out_enable:
|
||||
perf_event_enable(per_cpu(watchdog_ev, cpu));
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void watchdog_nmi_disable(unsigned int cpu)
|
||||
{
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
|
||||
if (event) {
|
||||
perf_event_disable(event);
|
||||
per_cpu(watchdog_ev, cpu) = NULL;
|
||||
|
||||
/* should be in cleanup, but blocks oprofile */
|
||||
perf_event_release_kernel(event);
|
||||
}
|
||||
if (cpu == 0) {
|
||||
/* watchdog_nmi_enable() expects this to be zero initially. */
|
||||
cpu0_err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static int watchdog_nmi_enable(unsigned int cpu) { return 0; }
|
||||
static void watchdog_nmi_disable(unsigned int cpu) { return; }
|
||||
#endif /* CONFIG_HARDLOCKUP_DETECTOR */
|
||||
|
||||
static struct smp_hotplug_thread watchdog_threads = {
|
||||
.store = &softlockup_watchdog,
|
||||
.thread_should_run = watchdog_should_run,
|
||||
@@ -706,12 +472,16 @@ static int watchdog_park_threads(void)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
|
||||
atomic_set(&watchdog_park_in_progress, 1);
|
||||
|
||||
for_each_watchdog_cpu(cpu) {
|
||||
ret = kthread_park(per_cpu(softlockup_watchdog, cpu));
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
atomic_set(&watchdog_park_in_progress, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Detect hard lockups on a system
|
||||
*
|
||||
* started by Don Zickus, Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* Note: Most of this code is borrowed heavily from the original softlockup
|
||||
* detector, so thanks to Ingo for the initial implementation.
|
||||
* Some chunks also taken from the old x86-specific nmi watchdog code, thanks
|
||||
* to those contributors as well.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "NMI watchdog: " fmt
|
||||
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/irq_regs.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
static DEFINE_PER_CPU(bool, hard_watchdog_warn);
|
||||
static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
|
||||
static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
|
||||
|
||||
/* boot commands */
|
||||
/*
|
||||
* Should we panic when a soft-lockup or hard-lockup occurs:
|
||||
*/
|
||||
unsigned int __read_mostly hardlockup_panic =
|
||||
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
|
||||
static unsigned long hardlockup_allcpu_dumped;
|
||||
/*
|
||||
* We may not want to enable hard lockup detection by default in all cases,
|
||||
* for example when running the kernel as a guest on a hypervisor. In these
|
||||
* cases this function can be called to disable hard lockup detection. This
|
||||
* function should only be executed once by the boot processor before the
|
||||
* kernel command line parameters are parsed, because otherwise it is not
|
||||
* possible to override this in hardlockup_panic_setup().
|
||||
*/
|
||||
void hardlockup_detector_disable(void)
|
||||
{
|
||||
watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
|
||||
}
|
||||
|
||||
static int __init hardlockup_panic_setup(char *str)
|
||||
{
|
||||
if (!strncmp(str, "panic", 5))
|
||||
hardlockup_panic = 1;
|
||||
else if (!strncmp(str, "nopanic", 7))
|
||||
hardlockup_panic = 0;
|
||||
else if (!strncmp(str, "0", 1))
|
||||
watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
|
||||
else if (!strncmp(str, "1", 1))
|
||||
watchdog_enabled |= NMI_WATCHDOG_ENABLED;
|
||||
return 1;
|
||||
}
|
||||
__setup("nmi_watchdog=", hardlockup_panic_setup);
|
||||
|
||||
void touch_nmi_watchdog(void)
|
||||
{
|
||||
/*
|
||||
* Using __raw here because some code paths have
|
||||
* preemption enabled. If preemption is enabled
|
||||
* then interrupts should be enabled too, in which
|
||||
* case we shouldn't have to worry about the watchdog
|
||||
* going off.
|
||||
*/
|
||||
raw_cpu_write(watchdog_nmi_touch, true);
|
||||
touch_softlockup_watchdog();
|
||||
}
|
||||
EXPORT_SYMBOL(touch_nmi_watchdog);
|
||||
|
||||
static struct perf_event_attr wd_hw_attr = {
|
||||
.type = PERF_TYPE_HARDWARE,
|
||||
.config = PERF_COUNT_HW_CPU_CYCLES,
|
||||
.size = sizeof(struct perf_event_attr),
|
||||
.pinned = 1,
|
||||
.disabled = 1,
|
||||
};
|
||||
|
||||
/* Callback function for perf event subsystem */
|
||||
static void watchdog_overflow_callback(struct perf_event *event,
|
||||
struct perf_sample_data *data,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
/* Ensure the watchdog never gets throttled */
|
||||
event->hw.interrupts = 0;
|
||||
|
||||
if (atomic_read(&watchdog_park_in_progress) != 0)
|
||||
return;
|
||||
|
||||
if (__this_cpu_read(watchdog_nmi_touch) == true) {
|
||||
__this_cpu_write(watchdog_nmi_touch, false);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for a hardlockup
|
||||
* This is done by making sure our timer interrupt
|
||||
* is incrementing. The timer interrupt should have
|
||||
* fired multiple times before we overflow'd. If it hasn't
|
||||
* then this is a good indication the cpu is stuck
|
||||
*/
|
||||
if (is_hardlockup()) {
|
||||
int this_cpu = smp_processor_id();
|
||||
|
||||
/* only print hardlockups once */
|
||||
if (__this_cpu_read(hard_watchdog_warn) == true)
|
||||
return;
|
||||
|
||||
pr_emerg("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
|
||||
print_modules();
|
||||
print_irqtrace_events(current);
|
||||
if (regs)
|
||||
show_regs(regs);
|
||||
else
|
||||
dump_stack();
|
||||
|
||||
/*
|
||||
* Perform all-CPU dump only once to avoid multiple hardlockups
|
||||
* generating interleaving traces
|
||||
*/
|
||||
if (sysctl_hardlockup_all_cpu_backtrace &&
|
||||
!test_and_set_bit(0, &hardlockup_allcpu_dumped))
|
||||
trigger_allbutself_cpu_backtrace();
|
||||
|
||||
if (hardlockup_panic)
|
||||
nmi_panic(regs, "Hard LOCKUP");
|
||||
|
||||
__this_cpu_write(hard_watchdog_warn, true);
|
||||
return;
|
||||
}
|
||||
|
||||
__this_cpu_write(hard_watchdog_warn, false);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* People like the simple clean cpu node info on boot.
|
||||
* Reduce the watchdog noise by only printing messages
|
||||
* that are different from what cpu0 displayed.
|
||||
*/
|
||||
static unsigned long cpu0_err;
|
||||
|
||||
int watchdog_nmi_enable(unsigned int cpu)
|
||||
{
|
||||
struct perf_event_attr *wd_attr;
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
|
||||
/* nothing to do if the hard lockup detector is disabled */
|
||||
if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
|
||||
goto out;
|
||||
|
||||
/* is it already setup and enabled? */
|
||||
if (event && event->state > PERF_EVENT_STATE_OFF)
|
||||
goto out;
|
||||
|
||||
/* it is setup but not enabled */
|
||||
if (event != NULL)
|
||||
goto out_enable;
|
||||
|
||||
wd_attr = &wd_hw_attr;
|
||||
wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
|
||||
|
||||
/* Try to register using hardware perf events */
|
||||
event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
|
||||
|
||||
/* save cpu0 error for future comparision */
|
||||
if (cpu == 0 && IS_ERR(event))
|
||||
cpu0_err = PTR_ERR(event);
|
||||
|
||||
if (!IS_ERR(event)) {
|
||||
/* only print for cpu0 or different than cpu0 */
|
||||
if (cpu == 0 || cpu0_err)
|
||||
pr_info("enabled on all CPUs, permanently consumes one hw-PMU counter.\n");
|
||||
goto out_save;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the hard lockup detector if _any_ CPU fails to set up
|
||||
* set up the hardware perf event. The watchdog() function checks
|
||||
* the NMI_WATCHDOG_ENABLED bit periodically.
|
||||
*
|
||||
* The barriers are for syncing up watchdog_enabled across all the
|
||||
* cpus, as clear_bit() does not use barriers.
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(NMI_WATCHDOG_ENABLED_BIT, &watchdog_enabled);
|
||||
smp_mb__after_atomic();
|
||||
|
||||
/* skip displaying the same error again */
|
||||
if (cpu > 0 && (PTR_ERR(event) == cpu0_err))
|
||||
return PTR_ERR(event);
|
||||
|
||||
/* vary the KERN level based on the returned errno */
|
||||
if (PTR_ERR(event) == -EOPNOTSUPP)
|
||||
pr_info("disabled (cpu%i): not supported (no LAPIC?)\n", cpu);
|
||||
else if (PTR_ERR(event) == -ENOENT)
|
||||
pr_warn("disabled (cpu%i): hardware events not enabled\n",
|
||||
cpu);
|
||||
else
|
||||
pr_err("disabled (cpu%i): unable to create perf event: %ld\n",
|
||||
cpu, PTR_ERR(event));
|
||||
|
||||
pr_info("Shutting down hard lockup detector on all cpus\n");
|
||||
|
||||
return PTR_ERR(event);
|
||||
|
||||
/* success path */
|
||||
out_save:
|
||||
per_cpu(watchdog_ev, cpu) = event;
|
||||
out_enable:
|
||||
perf_event_enable(per_cpu(watchdog_ev, cpu));
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void watchdog_nmi_disable(unsigned int cpu)
|
||||
{
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
|
||||
if (event) {
|
||||
perf_event_disable(event);
|
||||
per_cpu(watchdog_ev, cpu) = NULL;
|
||||
|
||||
/* should be in cleanup, but blocks oprofile */
|
||||
perf_event_release_kernel(event);
|
||||
}
|
||||
if (cpu == 0) {
|
||||
/* watchdog_nmi_enable() expects this to be zero initially. */
|
||||
cpu0_err = 0;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/printk.h>
|
||||
@@ -298,6 +299,8 @@ void kasan_report(unsigned long addr, size_t size,
|
||||
if (likely(!kasan_report_enabled()))
|
||||
return;
|
||||
|
||||
disable_trace_on_warning();
|
||||
|
||||
info.access_addr = (void *)addr;
|
||||
info.access_size = size;
|
||||
info.is_write = is_write;
|
||||
|
||||
+9
-2
@@ -412,6 +412,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
|
||||
struct shrink_control *sc, unsigned long nr_to_split)
|
||||
{
|
||||
LIST_HEAD(list), *pos, *next;
|
||||
LIST_HEAD(to_remove);
|
||||
struct inode *inode;
|
||||
struct shmem_inode_info *info;
|
||||
struct page *page;
|
||||
@@ -438,9 +439,8 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
|
||||
/* Check if there's anything to gain */
|
||||
if (round_up(inode->i_size, PAGE_SIZE) ==
|
||||
round_up(inode->i_size, HPAGE_PMD_SIZE)) {
|
||||
list_del_init(&info->shrinklist);
|
||||
list_move(&info->shrinklist, &to_remove);
|
||||
removed++;
|
||||
iput(inode);
|
||||
goto next;
|
||||
}
|
||||
|
||||
@@ -451,6 +451,13 @@ next:
|
||||
}
|
||||
spin_unlock(&sbinfo->shrinklist_lock);
|
||||
|
||||
list_for_each_safe(pos, next, &to_remove) {
|
||||
info = list_entry(pos, struct shmem_inode_info, shrinklist);
|
||||
inode = &info->vfs_inode;
|
||||
list_del_init(&info->shrinklist);
|
||||
iput(inode);
|
||||
}
|
||||
|
||||
list_for_each_safe(pos, next, &list) {
|
||||
int ret;
|
||||
|
||||
|
||||
+6
-3
@@ -1394,9 +1394,12 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
|
||||
if (regs.len > reglen)
|
||||
regs.len = reglen;
|
||||
|
||||
regbuf = vzalloc(reglen);
|
||||
if (reglen && !regbuf)
|
||||
return -ENOMEM;
|
||||
regbuf = NULL;
|
||||
if (reglen) {
|
||||
regbuf = vzalloc(reglen);
|
||||
if (!regbuf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ops->get_regs(dev, ®s, regbuf);
|
||||
|
||||
|
||||
+6
-6
@@ -1263,7 +1263,7 @@ void __init arp_init(void)
|
||||
/*
|
||||
* ax25 -> ASCII conversion
|
||||
*/
|
||||
static char *ax2asc2(ax25_address *a, char *buf)
|
||||
static void ax2asc2(ax25_address *a, char *buf)
|
||||
{
|
||||
char c, *s;
|
||||
int n;
|
||||
@@ -1285,10 +1285,10 @@ static char *ax2asc2(ax25_address *a, char *buf)
|
||||
*s++ = n + '0';
|
||||
*s++ = '\0';
|
||||
|
||||
if (*buf == '\0' || *buf == '-')
|
||||
return "*";
|
||||
|
||||
return buf;
|
||||
if (*buf == '\0' || *buf == '-') {
|
||||
buf[0] = '*';
|
||||
buf[1] = '\0';
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_AX25 */
|
||||
|
||||
@@ -1322,7 +1322,7 @@ static void arp_format_neigh_entry(struct seq_file *seq,
|
||||
}
|
||||
#endif
|
||||
sprintf(tbuf, "%pI4", n->primary_key);
|
||||
seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n",
|
||||
seq_printf(seq, "%-16s 0x%-10x0x%-10x%-17s * %s\n",
|
||||
tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
|
||||
read_unlock(&n->lock);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ static void jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
|
||||
(fwmark > 0 && skb->mark == fwmark)) &&
|
||||
(full || tp->snd_cwnd != tcp_probe.lastcwnd)) {
|
||||
|
||||
spin_lock(&tcp_probe.lock);
|
||||
spin_lock_bh(&tcp_probe.lock);
|
||||
/* If log fills, just silently drop */
|
||||
if (tcp_probe_avail() > 1) {
|
||||
struct tcp_log *p = tcp_probe.log + tcp_probe.head;
|
||||
@@ -157,7 +157,7 @@ static void jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
|
||||
tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1);
|
||||
}
|
||||
tcp_probe.lastcwnd = tp->snd_cwnd;
|
||||
spin_unlock(&tcp_probe.lock);
|
||||
spin_unlock_bh(&tcp_probe.lock);
|
||||
|
||||
wake_up(&tcp_probe.wait);
|
||||
}
|
||||
|
||||
+14
-2
@@ -3416,9 +3416,15 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
|
||||
}
|
||||
|
||||
if (idev) {
|
||||
if (idev->if_flags & IF_READY)
|
||||
/* device is already configured. */
|
||||
if (idev->if_flags & IF_READY) {
|
||||
/* device is already configured -
|
||||
* but resend MLD reports, we might
|
||||
* have roamed and need to update
|
||||
* multicast snooping switches
|
||||
*/
|
||||
ipv6_mc_up(idev);
|
||||
break;
|
||||
}
|
||||
idev->if_flags |= IF_READY;
|
||||
}
|
||||
|
||||
@@ -4033,6 +4039,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id)
|
||||
|
||||
if (bump_id)
|
||||
rt_genid_bump_ipv6(dev_net(dev));
|
||||
|
||||
/* Make sure that a new temporary address will be created
|
||||
* before this temporary address becomes deprecated.
|
||||
*/
|
||||
if (ifp->flags & IFA_F_TEMPORARY)
|
||||
addrconf_verify_rtnl();
|
||||
}
|
||||
|
||||
static void addrconf_dad_run(struct inet6_dev *idev)
|
||||
|
||||
+9
-5
@@ -167,18 +167,22 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
if (np->sndflow)
|
||||
fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
|
||||
|
||||
addr_type = ipv6_addr_type(&usin->sin6_addr);
|
||||
|
||||
if (addr_type == IPV6_ADDR_ANY) {
|
||||
if (ipv6_addr_any(&usin->sin6_addr)) {
|
||||
/*
|
||||
* connect to self
|
||||
*/
|
||||
usin->sin6_addr.s6_addr[15] = 0x01;
|
||||
if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
|
||||
ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
|
||||
&usin->sin6_addr);
|
||||
else
|
||||
usin->sin6_addr = in6addr_loopback;
|
||||
}
|
||||
|
||||
addr_type = ipv6_addr_type(&usin->sin6_addr);
|
||||
|
||||
daddr = &usin->sin6_addr;
|
||||
|
||||
if (addr_type == IPV6_ADDR_MAPPED) {
|
||||
if (addr_type & IPV6_ADDR_MAPPED) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (__ipv6_only_sock(sk)) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user