Merge "defconfig: sdm845: Disable msm serial console driver" into msm-4.9
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 18f0186..b939cbf 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -346,7 +346,7 @@
alloc-ranges = <0 0x00000000 0 0xffffffff>;
reusable;
alignment = <0 0x400000>;
- size = <0 0x800000>;
+ size = <0 0xc00000>;
};
qseecom_mem: qseecom_region {
@@ -707,6 +707,12 @@
< 1651200 960000 >;
};
+ cpu_pmu: cpu-pmu {
+ compatible = "arm,armv8-pmuv3";
+ qcom,irq-is-percpu;
+ interrupts = <1 5 4>;
+ };
+
clock_gcc: qcom,gcc@100000 {
compatible = "qcom,gcc-sdm845", "syscon";
reg = <0x100000 0x1f0000>;
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 2f8d275..852548c 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -867,8 +867,6 @@
{
unsigned long config_base = 0;
- if (attr->exclude_idle)
- return -EPERM;
if (is_kernel_in_hyp_mode() &&
attr->exclude_kernel != attr->exclude_hv)
return -EINVAL;
@@ -975,11 +973,74 @@
ARRAY_SIZE(pmceid));
}
+static void armv8pmu_idle_update(struct arm_pmu *cpu_pmu)
+{
+ struct pmu_hw_events *hw_events;
+ struct perf_event *event;
+ int idx;
+
+ if (!cpu_pmu)
+ return;
+
+ hw_events = this_cpu_ptr(cpu_pmu->hw_events);
+
+ if (!hw_events)
+ return;
+
+ for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
+
+ if (!test_bit(idx, hw_events->used_mask))
+ continue;
+
+ event = hw_events->events[idx];
+
+ if (!event || !event->attr.exclude_idle ||
+ event->state != PERF_EVENT_STATE_ACTIVE)
+ continue;
+
+ cpu_pmu->pmu.read(event);
+ }
+}
+
+struct arm_pmu_and_idle_nb {
+ struct arm_pmu *cpu_pmu;
+ struct notifier_block perf_cpu_idle_nb;
+};
+
+static int perf_cpu_idle_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct arm_pmu_and_idle_nb *pmu_nb = container_of(nb,
+ struct arm_pmu_and_idle_nb, perf_cpu_idle_nb);
+
+ if (action == IDLE_START)
+ armv8pmu_idle_update(pmu_nb->cpu_pmu);
+
+ return NOTIFY_OK;
+}
+
static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu)
{
- return smp_call_function_any(&cpu_pmu->supported_cpus,
+ int ret;
+ struct arm_pmu_and_idle_nb *pmu_idle_nb;
+
+ pmu_idle_nb = devm_kzalloc(&cpu_pmu->plat_device->dev,
+ sizeof(*pmu_idle_nb), GFP_KERNEL);
+ if (!pmu_idle_nb)
+ return -ENOMEM;
+
+ pmu_idle_nb->cpu_pmu = cpu_pmu;
+ pmu_idle_nb->perf_cpu_idle_nb.notifier_call = perf_cpu_idle_notifier;
+ idle_notifier_register(&pmu_idle_nb->perf_cpu_idle_nb);
+
+ ret = smp_call_function_any(&cpu_pmu->supported_cpus,
__armv8pmu_probe_pmu,
cpu_pmu, 1);
+
+ if (ret)
+ idle_notifier_unregister(&pmu_idle_nb->perf_cpu_idle_nb);
+
+ return ret;
}
static void armv8_pmu_init(struct arm_pmu *cpu_pmu)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 1c37978..68d7653 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -3063,6 +3063,7 @@
.regulator_disable_poll = adreno_regulator_disable_poll,
.clk_set_options = adreno_clk_set_options,
.gpu_model = adreno_gpu_model,
+ .stop_fault_timer = adreno_dispatcher_stop_fault_timer,
};
static struct platform_driver adreno_platform_driver = {
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 0211a17..54d4bf7 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -899,6 +899,72 @@
}
/*
+ * a6xx_hm_sptprac_enable() - Turn on HM and SPTPRAC
+ * @device: Pointer to KGSL device
+ */
+static int a6xx_hm_sptprac_enable(struct kgsl_device *device)
+{
+ int ret = 0;
+ struct gmu_device *gmu = &device->gmu;
+
+ /* If GMU does not control HM we must */
+ if (gmu->idle_level < GPU_HW_IFPC) {
+ ret = a6xx_hm_enable(ADRENO_DEVICE(device));
+ if (ret) {
+ dev_err(&gmu->pdev->dev, "Failed to power on GPU HM\n");
+ return ret;
+ }
+ }
+
+ /* If GMU does not control SPTPRAC we must */
+ if (gmu->idle_level < GPU_HW_SPTP_PC) {
+ ret = a6xx_sptprac_enable(ADRENO_DEVICE(device));
+ if (ret) {
+ a6xx_hm_disable(ADRENO_DEVICE(device));
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * a6xx_hm_sptprac_disable() - Turn off SPTPRAC and HM
+ * @device: Pointer to KGSL device
+ */
+static int a6xx_hm_sptprac_disable(struct kgsl_device *device)
+{
+ int ret = 0;
+ struct gmu_device *gmu = &device->gmu;
+
+ /* If GMU does not control SPTPRAC we must */
+ if (gmu->idle_level < GPU_HW_SPTP_PC)
+ a6xx_sptprac_disable(ADRENO_DEVICE(device));
+
+ /* If GMU does not control HM we must */
+ if (gmu->idle_level < GPU_HW_IFPC) {
+ ret = a6xx_hm_disable(ADRENO_DEVICE(device));
+ if (ret)
+ dev_err(&gmu->pdev->dev, "Failed to power off GPU HM\n");
+ }
+
+ return ret;
+}
+
+/*
+ * a6xx_hm_sptprac_control() - Turn HM and SPTPRAC on or off
+ * @device: Pointer to KGSL device
+ * @on: True to turn on or false to turn off
+ */
+static int a6xx_hm_sptprac_control(struct kgsl_device *device, bool on)
+{
+ if (on)
+ return a6xx_hm_sptprac_enable(device);
+ else
+ return a6xx_hm_sptprac_disable(device);
+}
+
+/*
* a6xx_gfx_rail_on() - request GMU to power GPU at given OPP.
* @device: Pointer to KGSL device
*
@@ -976,7 +1042,7 @@
{
struct gmu_device *gmu = &device->gmu;
struct device *dev = &gmu->pdev->dev;
- int ret;
+ int ret = 0;
if (device->state != KGSL_STATE_INIT &&
device->state != KGSL_STATE_SUSPEND) {
@@ -1002,26 +1068,11 @@
0xFFFFFFFF))
goto error_rsc;
- /* If GMU does not control HM we must */
- if (gmu->idle_level < GPU_HW_IFPC) {
- ret = a6xx_hm_enable(ADRENO_DEVICE(device));
- if (ret) {
- dev_err(dev, "Failed to power on GPU HM\n");
- return ret;
- }
- }
-
- /* If GMU does not control SPTP we must */
- if (gmu->idle_level < GPU_HW_SPTP_PC) {
- ret = a6xx_sptprac_enable(ADRENO_DEVICE(device));
- if (ret) {
- a6xx_hm_disable(ADRENO_DEVICE(device));
- return ret;
- }
- }
+ /* Turn on the HM and SPTP head switches */
+ ret = a6xx_hm_sptprac_control(device, true);
}
- return 0;
+ return ret;
error_rsc:
dev_err(dev, "GPU RSC sequence stuck in waking up GPU\n");
@@ -1031,19 +1082,10 @@
static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
{
struct gmu_device *gmu = &device->gmu;
- struct device *dev = &gmu->pdev->dev;
- int val, ret;
+ int val, ret = 0;
- /* If GMU does not control SPTP we must */
- if (gmu->idle_level < GPU_HW_SPTP_PC)
- a6xx_sptprac_disable(ADRENO_DEVICE(device));
-
- /* If GMU does not control HM we must */
- if (gmu->idle_level < GPU_HW_IFPC) {
- ret = a6xx_hm_disable(ADRENO_DEVICE(device));
- if (ret)
- dev_err(dev, "Failed to power off GPU HM\n");
- }
+ /* Turn off the SPTP and HM head switches */
+ ret = a6xx_hm_sptprac_control(device, false);
/* RSC sleep sequence */
_regwrite(gmu->pdc_reg_virt, PDC_GPU_TIMESTAMP_UNIT1_EN_DRV0, 1);
@@ -1069,7 +1111,7 @@
/* FIXME: v2 has different procedure to trigger sequence */
- return 0;
+ return ret;
}
/*
@@ -1083,30 +1125,16 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct gmu_device *gmu = &device->gmu;
struct gmu_memdesc *mem_addr = gmu->hfi_mem;
- struct device *dev = &gmu->pdev->dev;
int ret, i;
a6xx_gmu_power_config(device);
- /* If GMU does not control HM then we must */
- if (gmu->idle_level < GPU_HW_IFPC) {
- ret = a6xx_hm_enable(adreno_dev);
- if (ret) {
- dev_err(dev, "Failed to power on GPU HM\n");
- return ret;
- }
- }
-
- /* If GMU does not control SPTP then we must */
- if (gmu->idle_level < GPU_HW_SPTP_PC) {
- ret = a6xx_sptprac_enable(adreno_dev);
- if (ret) {
- a6xx_hm_disable(adreno_dev);
- return ret;
- }
- }
-
if (boot_state == GMU_COLD_BOOT || boot_state == GMU_RESET) {
+ /* Turn on the HM and SPTP head switches */
+ ret = a6xx_hm_sptprac_control(device, true);
+ if (ret)
+ return ret;
+
/* Turn on TCM retention */
kgsl_gmu_regwrite(device, A6XX_GMU_GENERAL_7, 1);
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 4d1f1ad..ed5b714 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -208,6 +208,9 @@
if (!kgsl_state_is_awake(KGSL_DEVICE(adreno_dev)))
goto ret;
+ if (adreno_rb_empty(adreno_dev->cur_rb))
+ goto ret;
+
/* only check rbbm status to determine if GPU is idle */
adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, ®_rbbm_status);
@@ -2055,6 +2058,18 @@
return 0;
/*
+ * In the very unlikely case that the power is off, do nothing - the
+ * state will be reset on power up and everybody will be happy
+ */
+
+ if (!kgsl_state_is_awake(device) && (fault & ADRENO_SOFT_FAULT)) {
+ /* Clear the existing register values */
+ memset(adreno_ft_regs_val, 0,
+ adreno_ft_regs_num * sizeof(unsigned int));
+ return 0;
+ }
+
+ /*
* On A5xx and A6xx, read RBBM_STATUS3:SMMU_STALLED_ON_FAULT (BIT 24)
* to tell if this function was entered after a pagefault. If so, only
* proceed if the fault handler has already run in the IRQ thread,
@@ -2509,7 +2524,7 @@
if (!fault_detect_read_compare(adreno_dev)) {
adreno_set_gpu_fault(adreno_dev, ADRENO_SOFT_FAULT);
adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
- } else {
+ } else if (dispatcher->inflight > 0) {
mod_timer(&dispatcher->fault_timer,
jiffies + msecs_to_jiffies(_fault_timer_interval));
}
@@ -2554,6 +2569,20 @@
}
/**
+ * adreno_dispatcher_stop_fault_timer() - stop the dispatcher fault timer
+ * @device: pointer to the KGSL device structure
+ *
+ * Stop the dispatcher fault timer
+ */
+void adreno_dispatcher_stop_fault_timer(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
+
+ del_timer_sync(&dispatcher->fault_timer);
+}
+
+/**
* adreno_dispatcher_close() - close the dispatcher
* @adreno_dev: pointer to the adreno device structure
*
diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h
index cb9106f..72545db 100644
--- a/drivers/gpu/msm/adreno_dispatch.h
+++ b/drivers/gpu/msm/adreno_dispatch.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -108,6 +108,7 @@
int adreno_dispatcher_idle(struct adreno_device *adreno_dev);
void adreno_dispatcher_irq_fault(struct adreno_device *adreno_dev);
void adreno_dispatcher_stop(struct adreno_device *adreno_dev);
+void adreno_dispatcher_stop_fault_timer(struct kgsl_device *device);
int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv,
struct kgsl_context *context, struct kgsl_drawobj *drawobj[],
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index b4725c1..bf31c00 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -178,6 +178,7 @@
const char *name, struct clk *clk);
void (*gpu_model)(struct kgsl_device *device, char *str,
size_t bufsz);
+ void (*stop_fault_timer)(struct kgsl_device *device);
};
struct kgsl_ioctl {
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 4d38794..b3e2b6a 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -2621,6 +2621,7 @@
return -EBUSY;
}
+ device->ftbl->stop_fault_timer(device);
kgsl_pwrscale_midframe_timer_cancel(device);
/*
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 4d4fdf4..7c4654c 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -313,6 +313,7 @@
}
#endif
+#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
static void msm_geni_serial_wr_char(struct uart_port *uport, int ch)
{
geni_write_reg(ch, uport->membase, SE_GENI_TX_FIFOn);
@@ -384,6 +385,53 @@
spin_unlock(&uport->lock);
}
+static int handle_rx_console(struct uart_port *uport,
+ unsigned int rx_fifo_wc,
+ unsigned int rx_last_byte_valid,
+ unsigned int rx_last)
+{
+ int i, c;
+ unsigned char *rx_char;
+ struct tty_port *tport;
+ struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+
+ tport = &uport->state->port;
+
+ for (i = 0; i < rx_fifo_wc; i++) {
+ int bytes = 4;
+
+ *(msm_port->rx_fifo) =
+ geni_read_reg(uport->membase, SE_GENI_RX_FIFOn);
+ rx_char = (unsigned char *)msm_port->rx_fifo;
+
+ if (i == (rx_fifo_wc - 1)) {
+ if (rx_last && rx_last_byte_valid)
+ bytes = rx_last_byte_valid;
+ }
+ for (c = 0; c < bytes; c++) {
+ char flag = TTY_NORMAL;
+ int sysrq;
+
+ uport->icount.rx++;
+ sysrq = uart_handle_sysrq_char(uport, rx_char[c]);
+ if (!sysrq)
+ tty_insert_flip_char(tport, rx_char[c], flag);
+ }
+ }
+ tty_flip_buffer_push(tport);
+ return 0;
+}
+#else
+static int handle_rx_console(struct uart_port *uport,
+ unsigned int rx_fifo_wc,
+ unsigned int rx_last_byte_valid,
+ unsigned int rx_last)
+{
+ return -EPERM;
+}
+
+#endif /* (CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)) */
+
static void msm_geni_serial_start_tx(struct uart_port *uport)
{
unsigned int geni_m_irq_en;
@@ -476,43 +524,6 @@
WARN_ON(1);
}
-static int handle_rx_console(struct uart_port *uport,
- unsigned int rx_fifo_wc,
- unsigned int rx_last_byte_valid,
- unsigned int rx_last)
-{
- int i, c;
- unsigned char *rx_char;
- struct tty_port *tport;
- struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
-
- tport = &uport->state->port;
-
- for (i = 0; i < rx_fifo_wc; i++) {
- int bytes = 4;
-
- *(msm_port->rx_fifo) =
- geni_read_reg(uport->membase, SE_GENI_RX_FIFOn);
- rx_char = (unsigned char *)msm_port->rx_fifo;
-
- if (i == (rx_fifo_wc - 1)) {
- if (rx_last && rx_last_byte_valid)
- bytes = rx_last_byte_valid;
- }
- for (c = 0; c < bytes; c++) {
- char flag = TTY_NORMAL;
- int sysrq;
-
- uport->icount.rx++;
- sysrq = uart_handle_sysrq_char(uport, rx_char[c]);
- if (!sysrq)
- tty_insert_flip_char(tport, rx_char[c], flag);
- }
- }
- tty_flip_buffer_push(tport);
- return 0;
-}
-
static int handle_rx_hs(struct uart_port *uport,
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
@@ -943,6 +954,7 @@
return is_tx_empty;
}
+#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
static int __init msm_geni_console_setup(struct console *co, char *options)
{
struct uart_port *uport;
@@ -985,13 +997,100 @@
return uart_set_options(uport, co, baud, parity, bits, flow);
}
-static void msm_geni_serial_debug_init(struct uart_port *uport)
+static void
+msm_geni_serial_early_console_write(struct console *con, const char *s,
+ unsigned int n)
{
- struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+ struct earlycon_device *dev = con->data;
- msm_port->dbg = debugfs_create_dir(dev_name(uport->dev), NULL);
- if (IS_ERR_OR_NULL(msm_port->dbg))
- dev_err(uport->dev, "Failed to create dbg dir\n");
+ __msm_geni_serial_console_write(&dev->port, s, n);
+}
+
+static int __init
+msm_geni_serial_earlycon_setup(struct earlycon_device *dev,
+ const char *opt)
+{
+ struct uart_port *uport = &dev->port;
+ int ret = 0;
+ struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+ u32 tx_trans_cfg = 0;
+ u32 tx_parity_cfg = 0;
+ u32 rx_trans_cfg = 0;
+ u32 rx_parity_cfg = 0;
+ u32 stop_bit = 0;
+ u32 rx_stale = 0;
+ u32 bits_per_char = 0;
+ u32 s_clk_cfg = 0;
+ u32 baud = 115200;
+ u32 clk_div;
+ unsigned long clk_rate;
+
+ if (!uport->membase) {
+ ret = -ENOMEM;
+ goto exit_geni_serial_earlyconsetup;
+ }
+
+ if (get_se_proto(uport->membase) != UART) {
+ ret = -ENXIO;
+ goto exit_geni_serial_earlyconsetup;
+ }
+
+ msm_port->xfer_mode = FIFO_MODE;
+ set_rfr_wm(msm_port);
+ msm_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
+ msm_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
+ msm_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
+ geni_se_init(uport->membase, msm_port->xfer_mode, msm_port->rx_wm,
+ msm_port->rx_rfr);
+ /*
+ * Ignore Flow control.
+ * Disable Tx Parity.
+ * Don't check Parity during Rx.
+ * Disable Rx Parity.
+ * n = 8.
+ * Stop bit = 0.
+ * Stale timeout in bit-time (3 chars worth).
+ */
+ tx_trans_cfg |= UART_CTS_MASK;
+ tx_parity_cfg = 0;
+ rx_trans_cfg = 0;
+ rx_parity_cfg = 0;
+ bits_per_char = 0x8;
+ stop_bit = 0;
+ rx_stale = 0x18;
+ clk_div = get_clk_div_rate(baud, &clk_rate);
+ if (clk_div <= 0) {
+ ret = -EINVAL;
+ goto exit_geni_serial_earlyconsetup;
+ }
+
+ s_clk_cfg |= SER_CLK_EN;
+ s_clk_cfg |= (clk_div << CLK_DIV_SHFT);
+
+ geni_serial_write_term_regs(uport, 0, tx_trans_cfg,
+ tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
+ stop_bit, rx_stale, s_clk_cfg);
+
+ dev->con->write = msm_geni_serial_early_console_write;
+ dev->con->setup = NULL;
+ /*
+ * Ensure that the early console setup completes before
+ * returning.
+ */
+ mb();
+exit_geni_serial_earlyconsetup:
+ return ret;
+}
+OF_EARLYCON_DECLARE(msm_geni_serial, "qcom,msm-geni-uart",
+ msm_geni_serial_earlycon_setup);
+
+static int console_register(struct uart_driver *drv)
+{
+ return uart_register_driver(drv);
+}
+static void console_unregister(struct uart_driver *drv)
+{
+ uart_unregister_driver(drv);
}
static struct console cons_ops = {
@@ -1004,6 +1103,33 @@
.data = &msm_geni_console_driver,
};
+static struct uart_driver msm_geni_console_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "msm_geni_console",
+ .dev_name = "ttyMSM",
+ .nr = GENI_UART_NR_PORTS,
+ .cons = &cons_ops,
+};
+#else
+static int console_register(struct uart_driver *drv)
+{
+ return 0;
+}
+
+static void console_unregister(struct uart_driver *drv)
+{
+}
+#endif /* defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) */
+
+static void msm_geni_serial_debug_init(struct uart_port *uport)
+{
+ struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+
+ msm_port->dbg = debugfs_create_dir(dev_name(uport->dev), NULL);
+ if (IS_ERR_OR_NULL(msm_port->dbg))
+ dev_err(uport->dev, "Failed to create dbg dir\n");
+}
+
static const struct uart_ops msm_geni_serial_pops = {
.tx_empty = msm_geni_serial_tx_empty,
.stop_tx = msm_geni_serial_stop_tx,
@@ -1022,8 +1148,10 @@
};
static const struct of_device_id msm_geni_device_tbl[] = {
+#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
{ .compatible = "qcom,msm-geni-console",
.data = (void *)&msm_geni_console_driver},
+#endif
{ .compatible = "qcom,msm-geni-serial-hs",
.data = (void *)&msm_geni_serial_hs_driver},
{},
@@ -1189,92 +1317,6 @@
return 0;
}
-static void
-msm_geni_serial_early_console_write(struct console *con, const char *s,
- unsigned int n)
-{
- struct earlycon_device *dev = con->data;
-
- __msm_geni_serial_console_write(&dev->port, s, n);
-}
-
-static int __init
-msm_geni_serial_earlycon_setup(struct earlycon_device *dev,
- const char *opt)
-{
- struct uart_port *uport = &dev->port;
- int ret = 0;
- struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
- u32 tx_trans_cfg = 0;
- u32 tx_parity_cfg = 0;
- u32 rx_trans_cfg = 0;
- u32 rx_parity_cfg = 0;
- u32 stop_bit = 0;
- u32 rx_stale = 0;
- u32 bits_per_char = 0;
- u32 s_clk_cfg = 0;
- u32 baud = 115200;
- u32 clk_div;
- unsigned long clk_rate;
-
- if (!uport->membase) {
- ret = -ENOMEM;
- goto exit_geni_serial_earlyconsetup;
- }
-
- if (get_se_proto(uport->membase) != UART) {
- ret = -ENXIO;
- goto exit_geni_serial_earlyconsetup;
- }
-
- msm_port->xfer_mode = FIFO_MODE;
- set_rfr_wm(msm_port);
- msm_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
- msm_port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
- msm_port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
- geni_se_init(uport->membase, msm_port->xfer_mode, msm_port->rx_wm,
- msm_port->rx_rfr);
- /*
- * Ignore Flow control.
- * Disable Tx Parity.
- * Don't check Parity during Rx.
- * Disable Rx Parity.
- * n = 8.
- * Stop bit = 0.
- * Stale timeout in bit-time (3 chars worth).
- */
- tx_trans_cfg |= UART_CTS_MASK;
- tx_parity_cfg = 0;
- rx_trans_cfg = 0;
- rx_parity_cfg = 0;
- bits_per_char = 0x8;
- stop_bit = 0;
- rx_stale = 0x18;
- clk_div = get_clk_div_rate(baud, &clk_rate);
- if (clk_div <= 0) {
- ret = -EINVAL;
- goto exit_geni_serial_earlyconsetup;
- }
-
- s_clk_cfg |= SER_CLK_EN;
- s_clk_cfg |= (clk_div << CLK_DIV_SHFT);
-
- geni_serial_write_term_regs(uport, 0, tx_trans_cfg,
- tx_parity_cfg, rx_trans_cfg, rx_parity_cfg, bits_per_char,
- stop_bit, rx_stale, s_clk_cfg);
-
- dev->con->write = msm_geni_serial_early_console_write;
- dev->con->setup = NULL;
- /*
- * Ensure that the early console setup completes before
- * returning.
- */
- mb();
-exit_geni_serial_earlyconsetup:
- return ret;
-}
-OF_EARLYCON_DECLARE(msm_geni_serial, "qcom,msm-geni-uart",
- msm_geni_serial_earlycon_setup);
#ifdef CONFIG_PM
static int msm_geni_serial_runtime_suspend(struct device *dev)
@@ -1366,13 +1408,6 @@
},
};
-static struct uart_driver msm_geni_console_driver = {
- .owner = THIS_MODULE,
- .driver_name = "msm_geni_console",
- .dev_name = "ttyMSM",
- .nr = GENI_UART_NR_PORTS,
- .cons = &cons_ops,
-};
static struct uart_driver msm_geni_serial_hs_driver = {
.owner = THIS_MODULE,
@@ -1393,7 +1428,7 @@
msm_geni_serial_ports[i].uport.line = i;
}
- ret = uart_register_driver(&msm_geni_console_driver);
+ ret = console_register(&msm_geni_console_driver);
if (ret)
return ret;
@@ -1405,7 +1440,7 @@
ret = platform_driver_register(&msm_geni_serial_platform_driver);
if (ret) {
- uart_unregister_driver(&msm_geni_console_driver);
+ console_unregister(&msm_geni_console_driver);
uart_unregister_driver(&msm_geni_serial_hs_driver);
return ret;
}
@@ -1419,7 +1454,7 @@
{
platform_driver_unregister(&msm_geni_serial_platform_driver);
uart_unregister_driver(&msm_geni_serial_hs_driver);
- uart_unregister_driver(&msm_geni_console_driver);
+ console_unregister(&msm_geni_console_driver);
}
module_exit(msm_geni_serial_exit);
diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c
index daca68b..46df732 100644
--- a/drivers/usb/gadget/function/f_accessory.c
+++ b/drivers/usb/gadget/function/f_accessory.c
@@ -611,8 +611,7 @@
{
struct acc_dev *dev = fp->private_data;
struct usb_request *req;
- ssize_t r = count;
- unsigned xfer;
+ ssize_t r = count, xfer, len;
int ret = 0;
pr_debug("acc_read(%zu)\n", count);
@@ -633,6 +632,8 @@
goto done;
}
+ len = ALIGN(count, dev->ep_out->maxpacket);
+
if (dev->rx_done) {
// last req cancelled. try to get it.
req = dev->rx_req[0];
@@ -642,7 +643,7 @@
requeue_req:
/* queue a request */
req = dev->rx_req[0];
- req->length = count;
+ req->length = len;
dev->rx_done = 0;
ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
if (ret < 0) {
@@ -941,6 +942,8 @@
memset(dev->serial, 0, sizeof(dev->serial));
dev->start_requested = 0;
dev->audio_mode = 0;
+ strlcpy(dev->manufacturer, "Android", ACC_STRING_SIZE);
+ strlcpy(dev->model, "Android", ACC_STRING_SIZE);
}
}
@@ -1251,13 +1254,13 @@
INIT_DELAYED_WORK(&dev->start_work, acc_start_work);
INIT_WORK(&dev->hid_work, acc_hid_work);
- /* _acc_dev must be set before calling usb_gadget_register_driver */
- _acc_dev = dev;
-
ret = misc_register(&acc_device);
if (ret)
goto err;
+ /* _acc_dev must be set before calling usb_gadget_register_driver */
+ _acc_dev = dev;
+
return 0;
err:
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index db7903d..a2a9185 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -989,6 +989,7 @@
struct device *create_function_device(char *name);
+#define AUDIO_SOURCE_DEV_NAME_LENGTH 20
static struct usb_function_instance *audio_source_alloc_inst(void)
{
struct audio_source_instance *fi_audio;
@@ -997,6 +998,8 @@
struct device *dev;
void *err_ptr;
int err = 0;
+ char device_name[AUDIO_SOURCE_DEV_NAME_LENGTH];
+ static u8 count;
fi_audio = kzalloc(sizeof(*fi_audio), GFP_KERNEL);
if (!fi_audio)
@@ -1014,7 +1017,11 @@
config_group_init_type_name(&fi_audio->func_inst.group, "",
&audio_source_func_type);
- dev = create_function_device("f_audio_source");
+
+ snprintf(device_name, AUDIO_SOURCE_DEV_NAME_LENGTH,
+ "f_audio_source%d", count++);
+
+ dev = create_function_device(device_name);
if (IS_ERR(dev)) {
err_ptr = dev;
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index c807b12..12e94d5 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -1562,13 +1562,6 @@
event->bNotificationType, req->status);
/* FALLTHROUGH */
case 0:
- /*
- * handle multiple pending resp available
- * notifications by queuing same until we're done,
- * rest of the notification require queuing new
- * request.
- */
- gsi_ctrl_send_notification(gsi);
break;
}
}
@@ -1663,6 +1656,14 @@
gsi_ctrl_send_cpkt_tomodem(gsi, req->buf, 0);
}
+static void gsi_ctrl_send_response_complete(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ struct f_gsi *gsi = req->context;
+
+ gsi_ctrl_send_notification(gsi);
+}
+
static int
gsi_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
{
@@ -1749,6 +1750,8 @@
memcpy(req->buf, cpkt->buf, value);
gsi_ctrl_pkt_free(cpkt);
+ req->complete = gsi_ctrl_send_response_complete;
+ req->context = gsi;
log_event_dbg("copied encap_resp %d bytes",
value);
break;
@@ -3047,6 +3050,9 @@
{
struct gsi_opts *opts = container_of(f, struct gsi_opts, func_inst);
+ if (!opts->gsi)
+ return;
+
if (opts->gsi->c_port.ctrl_device.fops)
misc_deregister(&opts->gsi->c_port.ctrl_device);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 677a047..6d27dae 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4245,6 +4245,32 @@
struct ieee80211_regdomain *rd);
/**
+ * regulatory_hint_user - hint to the wireless core a regulatory domain
+ * which the driver has received from an application
+ * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain
+ * should be in. If @rd is set this should be NULL. Note that if you
+ * set this to NULL you should still set rd->alpha2 to some accepted
+ * alpha2.
+ * @user_reg_hint_type: the type of user regulatory hint.
+ *
+ * Wireless drivers can use this function to hint to the wireless core
+ * the current regulatory domain as specified by trusted applications,
+ * it is the driver's responsibilty to estbalish which applications it
+ * trusts.
+ *
+ * The wiphy should be registered to cfg80211 prior to this call.
+ * For cfg80211 drivers this means you must first use wiphy_register(),
+ * for mac80211 drivers you must first use ieee80211_register_hw().
+ *
+ * Drivers should check the return value, its possible you can get
+ * an -ENOMEM or an -EINVAL.
+ *
+ * Return: 0 on success. -ENOMEM, -EINVAL.
+ */
+int regulatory_hint_user(const char *alpha2,
+ enum nl80211_user_reg_hint_type user_reg_hint_type);
+
+/**
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
* @wiphy: the wireless device we want to process the regulatory domain on
* @regd: the custom regulatory domain to use for this wiphy
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 87b9cd9..113d325 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -372,6 +372,7 @@
static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
static DEFINE_PER_CPU(int, perf_sched_cb_usages);
static DEFINE_PER_CPU(struct pmu_event_list, pmu_sb_events);
+static DEFINE_PER_CPU(bool, is_idle);
static atomic_t nr_mmap_events __read_mostly;
static atomic_t nr_comm_events __read_mostly;
@@ -3605,23 +3606,31 @@
static int perf_event_read(struct perf_event *event, bool group)
{
int event_cpu, ret = 0;
+ bool active_event_skip_read = false;
/*
* If event is enabled and currently active on a CPU, update the
* value in the event structure:
*/
+ event_cpu = READ_ONCE(event->oncpu);
+
+ if (event->state == PERF_EVENT_STATE_ACTIVE) {
+ if ((unsigned int)event_cpu >= nr_cpu_ids)
+ return 0;
+ if (cpu_isolated(event_cpu) ||
+ (event->attr.exclude_idle &&
+ per_cpu(is_idle, event_cpu)))
+ active_event_skip_read = true;
+ }
+
if (event->state == PERF_EVENT_STATE_ACTIVE &&
- !cpu_isolated(event->oncpu)) {
+ !active_event_skip_read) {
struct perf_read_data data = {
.event = event,
.group = group,
.ret = 0,
};
- event_cpu = READ_ONCE(event->oncpu);
- if ((unsigned)event_cpu >= nr_cpu_ids)
- return 0;
-
preempt_disable();
event_cpu = __perf_event_read_cpu(event, event_cpu);
@@ -3635,10 +3644,12 @@
* Therefore, either way, we'll have an up-to-date event count
* after this.
*/
- (void)smp_call_function_single(event_cpu, __perf_event_read, &data, 1);
+ (void)smp_call_function_single(event_cpu,
+ __perf_event_read, &data, 1);
preempt_enable();
ret = data.ret;
- } else if (event->state == PERF_EVENT_STATE_INACTIVE) {
+ } else if (event->state == PERF_EVENT_STATE_INACTIVE ||
+ active_event_skip_read) {
struct perf_event_context *ctx = event->ctx;
unsigned long flags;
@@ -3731,7 +3742,8 @@
if (!task) {
/* Must be root to operate on a CPU event: */
- if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+ if (!is_kernel_event(event) && perf_paranoid_cpu() &&
+ !capable(CAP_SYS_ADMIN))
return ERR_PTR(-EACCES);
/*
@@ -10849,6 +10861,26 @@
.priority = INT_MIN,
};
+static int event_idle_notif(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ switch (action) {
+ case IDLE_START:
+ __this_cpu_write(is_idle, true);
+ break;
+ case IDLE_END:
+ __this_cpu_write(is_idle, false);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block perf_event_idle_nb = {
+ .notifier_call = event_idle_notif,
+};
+
+
void __init perf_event_init(void)
{
int ret;
@@ -10862,6 +10894,7 @@
perf_pmu_register(&perf_task_clock, NULL, -1);
perf_tp_register();
perf_event_init_cpu(smp_processor_id());
+ idle_notifier_register(&perf_event_idle_nb);
register_reboot_notifier(&perf_reboot_notifier);
ret = init_hw_breakpoint();
diff --git a/kernel/trace/ipc_logging.c b/kernel/trace/ipc_logging.c
index fa7fd14..6d310ab 100644
--- a/kernel/trace/ipc_logging.c
+++ b/kernel/trace/ipc_logging.c
@@ -515,8 +515,8 @@
tsv_qtimer_write(&ectxt);
avail_size = (MAX_MSG_SIZE - (ectxt.offset + hdr_size));
va_start(arg_list, fmt);
- data_size = vsnprintf((ectxt.buff + ectxt.offset + hdr_size),
- avail_size, fmt, arg_list);
+ data_size = vscnprintf((ectxt.buff + ectxt.offset + hdr_size),
+ avail_size, fmt, arg_list);
va_end(arg_list);
tsv_write_header(&ectxt, TSV_TYPE_BYTE_ARRAY, data_size);
ectxt.offset += data_size;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index eeb23d2..bc0ebd4 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2340,6 +2340,7 @@
return 0;
}
+EXPORT_SYMBOL(regulatory_hint_user);
int regulatory_hint_indoor(bool is_indoor, u32 portid)
{
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index f6ced31..822ac90 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -28,9 +28,6 @@
bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
-int regulatory_hint_user(const char *alpha2,
- enum nl80211_user_reg_hint_type user_reg_hint_type);
-
/**
* regulatory_hint_indoor - hint operation in indoor env. or not
* @is_indoor: if true indicates that user space thinks that the