VERSION = 4
PATCHLEVEL = 9
- SUBLEVEL = 208
+ SUBLEVEL = 209
EXTRAVERSION =
NAME = Roaring Lionus
# Make variables (CC, etc...)
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
+LDGOLD = $(CROSS_COMPILE)ld.gold
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
-fno-strict-aliasing -fno-common -fshort-wchar \
-Werror-implicit-function-declaration \
-Wno-format-security \
- -std=gnu89
+ -Werror \
+ -std=gnu89 $(call cc-option,-fno-PIE)
+
+
KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
+ $(Q)mkdir -p $(srctree)/.git/hooks
# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;
CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
export CFLAGS_GCOV CFLAGS_KCOV
+# Make toolchain changes before including arch/$(SRCARCH)/Makefile to ensure
+# ar/cc/ld-* macros return correct values.
+ifdef CONFIG_LTO_CLANG
+# use GNU gold with LLVMgold for LTO linking, and LD for vmlinux_link
+LDFINAL_vmlinux := $(LD)
+LD := $(LDGOLD)
+LDFLAGS += -plugin LLVMgold.so
+# use llvm-ar for building symbol tables from IR files, and llvm-dis instead
+# of objdump for processing symbol versions and exports
+LLVM_AR := llvm-ar
+LLVM_DIS := llvm-dis
+export LLVM_AR LLVM_DIS
+endif
+
# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
# values of the respective KBUILD_* variables
ARCH_CPPFLAGS :=
KBUILD_CFLAGS += $(call cc-option,-fdata-sections,)
endif
+ifdef CONFIG_LTO_CLANG
+lto-clang-flags := -flto -fvisibility=hidden
+
+# allow disabling only clang LTO where needed
+DISABLE_LTO_CLANG := -fno-lto -fvisibility=default
+export DISABLE_LTO_CLANG
+endif
+
+ifdef CONFIG_LTO
+lto-flags := $(lto-clang-flags)
+KBUILD_CFLAGS += $(lto-flags)
+
+DISABLE_LTO := $(DISABLE_LTO_CLANG)
+export DISABLE_LTO
+
+# LDFINAL_vmlinux and LDFLAGS_FINAL_vmlinux can be set to override
+# the linker and flags for vmlinux_link.
+export LDFINAL_vmlinux LDFLAGS_FINAL_vmlinux
+endif
+
+ifdef CONFIG_CFI_CLANG
+cfi-clang-flags += -fsanitize=cfi
+DISABLE_CFI_CLANG := -fno-sanitize=cfi
+ifdef CONFIG_MODULES
+cfi-clang-flags += -fsanitize-cfi-cross-dso
+DISABLE_CFI_CLANG += -fno-sanitize-cfi-cross-dso
+endif
+ifdef CONFIG_CFI_PERMISSIVE
+cfi-clang-flags += -fsanitize-recover=cfi -fno-sanitize-trap=cfi
+endif
+
+# also disable CFI when LTO is disabled
+DISABLE_LTO_CLANG += $(DISABLE_CFI_CLANG)
+# allow disabling only clang CFI where needed
+export DISABLE_CFI_CLANG
+endif
+
+ifdef CONFIG_CFI
+# cfi-flags are re-tested in prepare-compiler-check
+cfi-flags := $(cfi-clang-flags)
+KBUILD_CFLAGS += $(cfi-flags)
+
+DISABLE_CFI := $(DISABLE_CFI_CLANG)
+DISABLE_LTO += $(DISABLE_CFI)
+export DISABLE_CFI
+endif
+
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os $(call cc-disable-warning,maybe-uninitialized,)
else
stackp-flag := -fstack-protector
stackp-name := REGULAR
else
-ifdef CONFIG_CC_STACKPROTECTOR_STRONG
+ifdef CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC
stackp-flag := -fstack-protector-strong
stackp-name := STRONG
else
# CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!")
PHONY += prepare-compiler-check
prepare-compiler-check: FORCE
+# Make sure we're using a supported toolchain with LTO_CLANG
+ifdef CONFIG_LTO_CLANG
+ ifneq ($(call clang-ifversion, -ge, 0500, y), y)
+ @echo Cannot use CONFIG_LTO_CLANG: requires clang 5.0 or later >&2 && exit 1
+ endif
+ ifneq ($(call gold-ifversion, -ge, 112000000, y), y)
+ @echo Cannot use CONFIG_LTO_CLANG: requires GNU gold 1.12 or later >&2 && exit 1
+ endif
+endif
+# Make sure compiler supports LTO flags
+ifdef lto-flags
+ ifeq ($(call cc-option, $(lto-flags)),)
+ @echo Cannot use CONFIG_LTO: $(lto-flags) not supported by compiler \
+ >&2 && exit 1
+ endif
+endif
# Make sure compiler supports requested stack protector flag.
ifdef stackp-name
ifeq ($(call cc-option, $(stackp-flag)),)
$(stackp-flag) available but compiler is broken >&2 && exit 1
endif
endif
+ifdef cfi-flags
+ ifeq ($(call cc-option, $(cfi-flags)),)
+ @echo Cannot use CONFIG_CFI: $(cfi-flags) not supported by compiler >&2 && exit 1
+ endif
+endif
@:
# Generate some files
* for zero-mapped memory areas etc..
*/
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) pfn_to_page(PHYS_PFN(__pa(empty_zero_page)))
+#define ZERO_PAGE(vaddr) phys_to_page(__pa_symbol(empty_zero_page))
#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
#define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte))
#define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID))
- /*
- * Execute-only user mappings do not have the PTE_USER bit set. All valid
- * kernel mappings have the PTE_UXN bit set.
- */
#define pte_valid_not_user(pte) \
- ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == (PTE_VALID | PTE_UXN))
+ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
#define pte_valid_young(pte) \
((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
#define pte_valid_user(pte) \
/*
* p??_access_permitted() is true for valid user mappings (subject to the
- * write permission check) other than user execute-only which do not have the
- * PTE_USER bit set. PROT_NONE mappings do not have the PTE_VALID bit set.
+ * write permission check). PROT_NONE mappings do not have the PTE_VALID bit
+ * set.
*/
#define pte_access_permitted(pte, write) \
(pte_valid_user(pte) && (!(write) || pte_write(pte)))
}
#endif
+#ifdef CONFIG_AMLOGIC_USER_FAULT
+static long get_user_pfn(struct mm_struct *mm, unsigned long addr)
+{
+ long pfn = -1;
+ pgd_t *pgd;
+
+ if (!mm || addr >= VMALLOC_START)
+ mm = &init_mm;
+
+ pgd = pgd_offset(mm, addr);
+
+ do {
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ break;
+
+ pud = pud_offset(pgd, addr);
+ if (pud_none(*pud) || pud_bad(*pud))
+ break;
+
+ pmd = pmd_offset(pud, addr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ break;
+
+ pte = pte_offset_map(pmd, addr);
+ pfn = pte_pfn(*pte);
+ pte_unmap(pte);
+ } while (0);
+
+ return pfn;
+}
+#endif /* CONFIG_AMLOGIC_USER_FAULT */
+
+
static bool is_el1_instruction_abort(unsigned int esr)
{
return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR;
do_exit(SIGKILL);
}
+#ifdef CONFIG_AMLOGIC_USER_FAULT
+void show_all_pfn(struct task_struct *task, struct pt_regs *regs)
+{
+ int i;
+ long pfn1;
+ char s1[10];
+ int top;
+
+ if (compat_user_mode(regs))
+ top = 15;
+ else
+ top = 31;
+ pr_info("reg value pfn ");
+ pr_cont("reg value pfn\n");
+ for (i = 0; i < top; i++) {
+ pfn1 = get_user_pfn(task->mm, regs->regs[i]);
+ if (pfn1 >= 0)
+ sprintf(s1, "%8lx", pfn1);
+ else
+ sprintf(s1, "--------");
+ if (i % 2 == 1)
+ pr_cont("r%-2d: %016llx %s\n", i, regs->regs[i], s1);
+ else
+ pr_info("r%-2d: %016llx %s ", i, regs->regs[i], s1);
+ }
+ pr_cont("\n");
+ pfn1 = get_user_pfn(task->mm, regs->pc);
+ if (pfn1 >= 0)
+ sprintf(s1, "%8lx", pfn1);
+ else
+ sprintf(s1, "--------");
+ pr_info("pc : %016llx %s\n", regs->pc, s1);
+ pfn1 = get_user_pfn(task->mm, regs->sp);
+ if (pfn1 >= 0)
+ sprintf(s1, "%8lx", pfn1);
+ else
+ sprintf(s1, "--------");
+ pr_info("sp : %016llx %s\n", regs->sp, s1);
+
+ pfn1 = get_user_pfn(task->mm, regs->unused);
+ if (pfn1 >= 0)
+ sprintf(s1, "%8lx", pfn1);
+ else
+ sprintf(s1, "--------");
+ pr_info("unused : %016llx %s\n", regs->unused, s1);
+}
+#endif /* CONFIG_AMLOGIC_USER_FAULT */
+
/*
* Something tried to access memory that isn't in our memory map. User mode
* accesses just cause a SIGSEGV
return fault;
}
-static inline bool is_permission_fault(unsigned int esr)
+static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs)
{
unsigned int ec = ESR_ELx_EC(esr);
unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
- return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM) ||
- (ec == ESR_ELx_EC_IABT_CUR && fsc_type == ESR_ELx_FSC_PERM);
+ if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR)
+ return false;
+
+ if (system_uses_ttbr0_pan())
+ return fsc_type == ESR_ELx_FSC_FAULT &&
+ (regs->pstate & PSR_PAN_BIT);
+ else
+ return fsc_type == ESR_ELx_FSC_PERM;
}
static bool is_el0_instruction_abort(unsigned int esr)
struct task_struct *tsk;
struct mm_struct *mm;
int fault, sig, code;
- unsigned long vm_flags = VM_READ | VM_WRITE;
+ unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC;
unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
if (notify_page_fault(regs, esr))
mm_flags |= FAULT_FLAG_WRITE;
}
- if (is_permission_fault(esr) && (addr < TASK_SIZE)) {
+ if (addr < TASK_SIZE && is_permission_fault(esr, regs)) {
/* regs->orig_addr_limit may be 0 if we entered from EL0 */
if (regs->orig_addr_limit == KERNEL_DS)
die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
{ do_bad, SIGBUS, 0, "unknown 63" },
};
+#ifdef CONFIG_AMLOGIC_VMAP
+asmlinkage static void die_wrap(const struct fault_info *inf,
+ struct pt_regs *regs, unsigned int esr,
+ unsigned long addr)
+{
+ struct siginfo info;
+
+ info.si_signo = inf->sig;
+ info.si_errno = 0;
+ info.si_code = inf->code;
+ info.si_addr = (void __user *)addr;
+ arm64_notify_die("", regs, &info, esr);
+}
+#endif
/*
* Dispatch a data abort to the relevant handler.
*/
struct pt_regs *regs)
{
const struct fault_info *inf = esr_to_fault_info(esr);
+#ifndef CONFIG_AMLOGIC_VMAP
struct siginfo info;
+#endif
if (!inf->fn(addr, esr, regs))
return;
pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n",
inf->name, esr, addr);
+#ifndef CONFIG_AMLOGIC_VMAP
info.si_signo = inf->sig;
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
arm64_notify_die("", regs, &info, esr);
+#else
+ die_wrap(inf, regs, esr, addr);
+#endif
}
asmlinkage void __exception do_el0_irq_bp_hardening(void)
chip = gpiod_to_chip(desc);
offset = gpio_chip_hwgpio(desc);
+ /*
+ * Open drain emulation using input mode may incorrectly report
+ * input here, fix that up.
+ */
+ if (test_bit(FLAG_OPEN_DRAIN, &desc->flags) &&
+ test_bit(FLAG_IS_OUT, &desc->flags))
+ return 0;
+
if (!chip->get_direction)
return status;
chip->set(chip, gpio_chip_hwgpio(desc), value);
}
+#ifdef CONFIG_AMLOGIC_PINCTRL
+static int _gpiod_set_pull(struct gpio_desc *desc, int value)
+{
+ struct gpio_chip *chip;
+ int status = -EINVAL;
+
+ chip = desc->gdev->chip;
+ if (!chip || !chip->set_pull) {
+ gpiod_warn(desc,
+ "%s: missing set_pull() operations\n",
+ __func__);
+ return -EIO;
+ }
+ if (test_bit(FLAG_REQUESTED, &desc->flags))
+ status = chip->set_pull(chip, gpio_chip_hwgpio(desc), value);
+
+ return status;
+}
+#endif
+
/*
* set multiple outputs on the same chip;
* use the chip's set_multiple function if available;
EXPORT_SYMBOL_GPL(gpiod_set_value);
/**
+ * gpiod_set_pull() - enable pull-down/up for the gpio, or disable.
+ * @desc: gpio whose value will be set
+ * @value: value to set
+ *
+ * This function should be called from contexts where we cannot sleep, and will
+ * complain if the GPIO chip functions potentially sleep.
+ */
+#ifdef CONFIG_AMLOGIC_PINCTRL
+int gpiod_set_pull(struct gpio_desc *desc, int value)
+{
+ VALIDATE_DESC(desc);
+ /* Should be using gpiod_set_pull_cansleep() */
+ WARN_ON(desc->gdev->chip->can_sleep);
+ return _gpiod_set_pull(desc, value);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_pull);
+#endif
+
+/**
* gpiod_set_raw_array_value() - assign values to an array of GPIOs
* @array_size: number of elements in the descriptor / value arrays
* @desc_array: array of GPIO descriptors whose values will be assigned
EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
/**
+ * gpiod_set_pull_cansleep() - enable pull-down/up for the gpio, or disable.
+ * @desc: gpio whose value will be set
+ * @value: value to set
+ *
+ * This function is to be called from contexts that can sleep.
+ */
+#ifdef CONFIG_AMLOGIC_PINCTRL
+int gpiod_set_pull_cansleep(struct gpio_desc *desc, int value)
+{
+ might_sleep_if(extra_checks);
+ VALIDATE_DESC(desc);
+ return _gpiod_set_pull(desc, value);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_pull_cansleep);
+#endif
+
+/**
* gpiod_set_raw_array_value_cansleep() - assign values to an array of GPIOs
* @array_size: number of elements in the descriptor / value arrays
* @desc_array: array of GPIO descriptors whose values will be assigned
struct gpio_desc *desc = ERR_PTR(-ENODEV);
bool active_low = false;
bool single_ended = false;
+#ifdef CONFIG_AMLOGIC_MODIFY
+ bool open_drain = false;
+#endif
int ret;
if (!fwnode)
if (!IS_ERR(desc)) {
active_low = flags & OF_GPIO_ACTIVE_LOW;
single_ended = flags & OF_GPIO_SINGLE_ENDED;
+#ifdef CONFIG_AMLOGIC_MODIFY
+ open_drain = flags & OF_GPIO_OPEN_DRAIN;
+#endif
}
} else if (is_acpi_node(fwnode)) {
struct acpi_gpio_info info;
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (single_ended) {
+#ifdef CONFIG_AMLOGIC_MODIFY
+ if (open_drain)
+#else
if (active_low)
+#endif
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
else
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
#include <linux/reset.h>
#include <linux/of_mdio.h>
#include "dwmac1000.h"
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+#include "stmmac_platform.h"
+#endif
+#ifdef CONFIG_DWMAC_MESON
+#include <phy_debug.h>
+#endif
+
+#include <linux/suspend.h>
+#define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */
- #define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES)
+ #define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16)
#define TSO_MAX_BUFF_SIZE (SZ_16K - 1)
/* Module parameters */
#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
+/*won't be valid unless enable amlogic priv code*/
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+#define TX_MONITOR
+#endif
+
+#ifdef TX_MONITOR
+static struct workqueue_struct *moniter_tx_wq;
+static struct delayed_work moniter_tx_worker;
+#endif
/**
* stmmac_verify_args - verify the driver parameters.
* Description: it checks the driver parameters and set a default in case of
return 0;
}
+#ifdef TX_MONITOR
+static int suspend_pm_notify(struct notifier_block *nb,
+ unsigned long mode, void *_unused)
+{
+ switch (mode) {
+ case PM_SUSPEND_PREPARE:
+ cancel_delayed_work_sync(&moniter_tx_worker);
+ flush_scheduled_work();
+ pr_info("receive suspend notify\n");
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static struct notifier_block suspend_pm_nb = {
+ .notifier_call = suspend_pm_notify,
+};
+#endif
/**
* stmmac_open - open entry point of the driver
* @dev : pointer to the device structure.
napi_enable(&priv->napi);
netif_start_queue(dev);
-
+#ifdef TX_MONITOR
+ queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ);
+#endif
return 0;
lpiirq_error:
* netdev structure and arrange for the device to be reset to a sane state
* in order to transmit a new packet.
*/
+#ifdef TX_MONITOR
+unsigned int timeout_err;
+#endif
static void stmmac_tx_timeout(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
return 0;
}
+#ifdef TX_MONITOR
+struct stmmac_priv *priv_monitor;
+static void moniter_tx_handler(struct work_struct *work)
+{
+ if (priv_monitor) {
+ if (timeout_err) {
+ pr_info("reset eth\n");
+ stmmac_release(priv_monitor->dev);
+ stmmac_open(priv_monitor->dev);
+ timeout_err = 0;
+ }
+ } else {
+ pr_info("device not init yet!\n");
+ }
+// queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ);
+}
+#endif
/**
* stmmac_dvr_probe
* @device: device pointer
struct net_device *ndev = NULL;
struct stmmac_priv *priv;
+#ifdef TX_MONITOR
+ int result = 0;
+ moniter_tx_wq = create_singlethread_workqueue("eth_moniter_tx_wq");
+ INIT_DELAYED_WORK(&moniter_tx_worker, moniter_tx_handler);
+ /*register pm notify callback*/
+ result = register_pm_notifier(&suspend_pm_nb);
+ if (result) {
+ unregister_pm_notifier(&suspend_pm_nb);
+ pr_info("register suspend notifier failed return %d\n", result);
+ }
+#endif
ndev = alloc_etherdev(sizeof(struct stmmac_priv));
if (!ndev)
return -ENOMEM;
goto error_netdev_register;
}
+#ifdef CONFIG_DWMAC_MESON
+ ret = gmac_create_sysfs(
+ mdiobus_get_phy(priv->mii, priv->plat->phy_addr), priv->ioaddr);
+#endif
+#ifdef TX_MONITOR
+ priv_monitor = priv;
+#endif
return ret;
error_netdev_register:
priv->hw->dma->stop_rx(priv->ioaddr);
priv->hw->dma->stop_tx(priv->ioaddr);
+#ifdef CONFIG_DWMAC_MESON
+ gmac_remove_sysfs(priv->phydev);
+#endif
+
stmmac_set_mac(priv->ioaddr, false);
netif_carrier_off(ndev);
unregister_netdev(ndev);
netif_device_detach(ndev);
netif_stop_queue(ndev);
+ /**
+ *napi_disable call might_sleep,if not irq restore
+ *It will warning bug
+ */
+ spin_unlock_irqrestore(&priv->lock, flags);
napi_disable(&priv->napi);
+ spin_lock_irqsave(&priv->lock, flags);
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+ del_timer_sync(&priv->txtimer);
+#endif
/* Stop TX/RX DMA */
priv->hw->dma->stop_tx(priv->ioaddr);
priv->hw->dma->stop_rx(priv->ioaddr);
/* Enable Power down mode by programming the PMT regs */
if (device_may_wakeup(priv->device)) {
- priv->hw->mac->pmt(priv->hw, priv->wolopts);
+ //priv->hw->mac->pmt(priv->hw, priv->wolopts);
+ priv->hw->mac->pmt(priv->hw, 0x1 << 5);
priv->irq_wake = 1;
} else {
stmmac_set_mac(priv->ioaddr, false);
stmmac_mdio_reset(priv->mii);
}
+#ifndef CONFIG_AMLOGIC_ETH_PRIVE
netif_device_attach(ndev);
-
+#endif
spin_lock_irqsave(&priv->lock, flags);
priv->cur_rx = 0;
stmmac_clear_descriptors(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
stmmac_hw_setup(ndev, false);
+ spin_lock_irqsave(&priv->lock, flags);
+
stmmac_init_tx_coalesce(priv);
stmmac_set_rx_mode(ndev);
-
+#ifdef CONFIG_AMLOGIC_ETH_PRIVE
+ netif_device_attach(ndev);
+#endif
napi_enable(&priv->napi);
netif_start_queue(ndev);
prz = cxt->przs[cxt->dump_write_cnt];
+ /*
+ * Since this is a new crash dump, we need to reset the buffer in
+ * case it still has an old dump present. Without this, the new dump
+ * will get appended, which would seriously confuse anything trying
+ * to check dump file contents. Specifically, ramoops_read_kmsg_hdr()
+ * expects to find a dump header in the beginning of buffer data, so
+ * we must to reset the buffer values, in order to ensure that the
+ * header will be written to the beginning of the buffer.
+ */
+ persistent_ram_zap(prz);
+
hlen = ramoops_write_kmsg_hdr(prz, compressed);
if (size + hlen > prz->buffer_size)
size = prz->buffer_size - hlen;
return 0;
}
+void notrace ramoops_console_write_buf(const char *buf, size_t size)
+{
+ struct ramoops_context *cxt = &oops_cxt;
+ persistent_ram_write(cxt->cprz, buf, size);
+}
+
static int ramoops_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
cxt->console_size, 0);
if (err)
goto fail_init_cprz;
-
err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
LINUX_VERSION_CODE);
if (err)
cxt->size, (unsigned long long)cxt->phys_addr,
cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ if (ramoops_ftrace_size) {
+ cxt->fprz->flags |= (PRZ_FLAG_NO_LOCK | PRZ_FLAG_BIG_LOCK);
+ ramoops_ftrace_en = 1;
+ }
+ pr_info("ramoops_io_en:%d %d old:0x%lx ftrace_size:0x%lx",
+ ramoops_io_en, ramoops_ftrace_en,
+ cxt->fprz ? (unsigned long)persistent_ram_old_size(cxt->fprz)
+ : 0, ramoops_ftrace_size);
+#endif
+
return 0;
fail_buf:
struct ftrace_ops *op, struct pt_regs *regs);
#else
/* See comment below, where ftrace_ops_list_func is defined */
-static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);
-#define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops)
+static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip,
+ struct ftrace_ops *op, struct pt_regs *regs);
+#define ftrace_ops_list_func ftrace_ops_no_ops
#endif
/*
}
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- avg = rec->time;
- do_div(avg, rec->counter);
+ avg = div64_ul(rec->time, rec->counter);
if (tracing_thresh && (avg < tracing_thresh))
goto out;
#endif
* Divide only 1000 for ns^2 -> us^2 conversion.
* trace_print_graph_duration will divide 1000 again.
*/
- do_div(stddev, rec->counter * (rec->counter - 1) * 1000);
+ stddev = div64_ul(stddev,
+ rec->counter * (rec->counter - 1) * 1000);
}
trace_seq_init(&s);
return 0;
}
-static int ftrace_process_locs(struct module *mod,
- unsigned long *start,
- unsigned long *end)
+static int __norecordmcount ftrace_process_locs(struct module *mod,
+ unsigned long *start,
+ unsigned long *end)
{
struct ftrace_page *start_pg;
struct ftrace_page *pg;
}
NOKPROBE_SYMBOL(ftrace_ops_list_func);
#else
-static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip)
+static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip,
+ struct ftrace_ops *op, struct pt_regs *regs)
{
__ftrace_ops_list_func(ip, parent_ip, NULL, NULL);
}
fgraph_graph_time = enable;
}
+void ftrace_graph_return_stub(struct ftrace_graph_ret *trace)
+{
+}
+
int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
{
return 0;
}
/* The callbacks that hook a function */
-trace_func_graph_ret_t ftrace_graph_return =
- (trace_func_graph_ret_t)ftrace_stub;
+trace_func_graph_ret_t ftrace_graph_return = ftrace_graph_return_stub;
trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
static trace_func_graph_ent_t __ftrace_graph_entry = ftrace_graph_entry_stub;
goto out;
ftrace_graph_active--;
- ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
+ ftrace_graph_return = ftrace_graph_return_stub;
ftrace_graph_entry = ftrace_graph_entry_stub;
__ftrace_graph_entry = ftrace_graph_entry_stub;
ftrace_shutdown(&graph_ops, FTRACE_STOP_FUNC_RET);
* MAP_PRIVATE r: (no) no r: (yes) yes r: (no) yes r: (no) yes
* w: (no) no w: (no) no w: (copy) copy w: (no) no
* x: (no) no x: (no) yes x: (no) yes x: (yes) yes
- *
- * On arm64, PROT_EXEC has the following behaviour for both MAP_SHARED and
- * MAP_PRIVATE:
- * r: (no) no
- * w: (no) no
- * x: (yes) yes
*/
pgprot_t protection_map[16] = {
__P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,
*/
static inline int is_mergeable_vma(struct vm_area_struct *vma,
struct file *file, unsigned long vm_flags,
- struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
+ const char __user *anon_name)
{
/*
* VM_SOFTDIRTY should not prevent from VMA merging, if we
return 0;
if (!is_mergeable_vm_userfaultfd_ctx(vma, vm_userfaultfd_ctx))
return 0;
+ if (vma_get_anon_name(vma) != anon_name)
+ return 0;
return 1;
}
can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
struct anon_vma *anon_vma, struct file *file,
pgoff_t vm_pgoff,
- struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
+ const char __user *anon_name)
{
- if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) &&
+ if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx, anon_name) &&
is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
if (vma->vm_pgoff == vm_pgoff)
return 1;
can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
struct anon_vma *anon_vma, struct file *file,
pgoff_t vm_pgoff,
- struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
+ const char __user *anon_name)
{
- if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) &&
+ if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx, anon_name) &&
is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
pgoff_t vm_pglen;
vm_pglen = vma_pages(vma);
}
/*
- * Given a mapping request (addr,end,vm_flags,file,pgoff), figure out
- * whether that can be merged with its predecessor or its successor.
- * Or both (it neatly fills a hole).
+ * Given a mapping request (addr,end,vm_flags,file,pgoff,anon_name),
+ * figure out whether that can be merged with its predecessor or its
+ * successor. Or both (it neatly fills a hole).
*
* In most cases - when called for mmap, brk or mremap - [addr,end) is
* certain not to be mapped by the time vma_merge is called; but when
unsigned long end, unsigned long vm_flags,
struct anon_vma *anon_vma, struct file *file,
pgoff_t pgoff, struct mempolicy *policy,
- struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
+ const char __user *anon_name)
{
pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
struct vm_area_struct *area, *next;
mpol_equal(vma_policy(prev), policy) &&
can_vma_merge_after(prev, vm_flags,
anon_vma, file, pgoff,
- vm_userfaultfd_ctx)) {
+ vm_userfaultfd_ctx,
+ anon_name)) {
/*
* OK, it can. Can we now merge in the successor as well?
*/
can_vma_merge_before(next, vm_flags,
anon_vma, file,
pgoff+pglen,
- vm_userfaultfd_ctx) &&
+ vm_userfaultfd_ctx,
+ anon_name) &&
is_mergeable_anon_vma(prev->anon_vma,
next->anon_vma, NULL)) {
/* cases 1, 6 */
mpol_equal(policy, vma_policy(next)) &&
can_vma_merge_before(next, vm_flags,
anon_vma, file, pgoff+pglen,
- vm_userfaultfd_ctx)) {
+ vm_userfaultfd_ctx,
+ anon_name)) {
if (prev && addr < prev->vm_end) /* case 4 */
err = __vma_adjust(prev, prev->vm_start,
addr, prev->vm_pgoff, NULL, next);
* Can we just expand an old mapping?
*/
vma = vma_merge(mm, prev, addr, addr + len, vm_flags,
- NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX);
+ NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX, NULL);
if (vma)
goto out;
return 0;
}
+EXPORT_SYMBOL(do_munmap);
int vm_munmap(unsigned long start, size_t len)
{
/* Can we just expand an old private anonymous mapping? */
vma = vma_merge(mm, prev, addr, addr + len, flags,
- NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX);
+ NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX, NULL);
if (vma)
goto out;
return NULL; /* should never get here */
new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
- vma->vm_userfaultfd_ctx);
+ vma->vm_userfaultfd_ctx, vma_get_anon_name(vma));
if (new_vma) {
/*
* Source vma may have been merged into new_vma
int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
int sysctl_tcp_early_retrans __read_mostly = 3;
int sysctl_tcp_invalid_ratelimit __read_mostly = HZ/2;
+int sysctl_tcp_default_init_rwnd __read_mostly = TCP_INIT_CWND * 2;
#define FLAG_DATA 0x01 /* Incoming frame contained data. */
#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
}
/* Ignore very old stuff early */
- if (!after(sp[used_sacks].end_seq, prior_snd_una))
+ if (!after(sp[used_sacks].end_seq, prior_snd_una)) {
+ if (i == 0)
+ first_sack_index = -1;
continue;
+ }
used_sacks++;
}
{
struct tcp_sock *tp = tcp_sk(sk);
- /* More than one full frame received... */
- if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss &&
+ /* More than one full frame received... */
+ if (((tp->rcv_nxt - tp->rcv_wup) >
+ (inet_csk(sk)->icsk_ack.rcv_mss) *
+ sysctl_tcp_delack_seg &&
/* ... and right edge of window advances far enough.
* (tcp_recvmsg() will send ACK otherwise). Or...
*/
}
EXPORT_SYMBOL(rfkill_resume_polling);
-#ifdef CONFIG_PM_SLEEP
-static int rfkill_suspend(struct device *dev)
+static __maybe_unused int rfkill_suspend(struct device *dev)
{
struct rfkill *rfkill = to_rfkill(dev);
return 0;
}
-static int rfkill_resume(struct device *dev)
+static __maybe_unused int rfkill_resume(struct device *dev)
{
struct rfkill *rfkill = to_rfkill(dev);
bool cur;
}
static SIMPLE_DEV_PM_OPS(rfkill_pm_ops, rfkill_suspend, rfkill_resume);
-#define RFKILL_PM_OPS (&rfkill_pm_ops)
-#else
-#define RFKILL_PM_OPS NULL
-#endif
static struct class rfkill_class = {
.name = "rfkill",
.dev_release = rfkill_release,
.dev_groups = rfkill_dev_groups,
.dev_uevent = rfkill_dev_uevent,
- .pm = RFKILL_PM_OPS,
+ .pm = IS_ENABLED(CONFIG_RFKILL_PM) ? &rfkill_pm_ops : NULL,
};
bool rfkill_blocked(struct rfkill *rfkill)
int __must_check rfkill_register(struct rfkill *rfkill)
{
static unsigned long rfkill_no;
- struct device *dev = &rfkill->dev;
+ struct device *dev;
int error;
- BUG_ON(!rfkill);
+ if (!rfkill)
+ return -EINVAL;
+
+ dev = &rfkill->dev;
mutex_lock(&rfkill_global_mutex);