* [RFT v2 1/4] perf cs-etm: Generate sample for missed packets
From: Arnaldo Carvalho de Melo @ 2018-05-25 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <03a53a72-8af5-02de-21a8-fd02a0974ed6@arm.com>
Em Fri, May 25, 2018 at 03:03:47PM +0100, Robert Walker escreveu:
> Hi Leo,
>
> Following the discussions from your reply to this with a simplified patch,
> this version of the patch works better as you also need to emit a branch
> sample when handling a CS_ETM_TRACE_ON packet to indicate the end of a block
> of trace.
>
> This patch does not break the output from perf inject to generate
> instruction samples for AutoFDO, so I am happy with that.
>
> Regards
>
> Rob
>
> Reviewed-by: Robert Walker <robert.walker@arm.com>
So, Leo, can you please resubmit, bumping the v2 to v3 (or the latest
one, I haven't fully reread this thread) add this "Reviewed-by: Robert"
tag and any other that people may have provided, so that I can merge it?
Thanks,
- Arnaldo
>
> On 22/05/18 09:39, Leo Yan wrote:
> > Hi Rob,
> >
> > On Mon, May 21, 2018 at 12:27:42PM +0100, Robert Walker wrote:
> > > Hi Leo,
> > >
> > > On 21/05/18 09:52, Leo Yan wrote:
> > > > Commit e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight
> > > > traces") reworks the samples generation flow from CoreSight trace to
> > > > match the correct format so Perf report tool can display the samples
> > > > properly. But the change has side effect for packet handling, it only
> > > > generate samples when 'prev_packet->last_instr_taken_branch' is true,
> > > > this results in the start tracing packet and exception packets are
> > > > dropped.
> > > >
> > > > This patch checks extra two conditions for complete samples:
> > > >
> > > > - If 'prev_packet->sample_type' is zero we can use this condition to
> > > > get to know this is the start tracing packet; for this case, the start
> > > > packet's end_addr is zero as well so we need to handle it in the
> > > > function cs_etm__last_executed_instr();
> > > >
> > > I think you also need to add something in to handle discontinuities in
> > > trace - for example it is possible to configure the ETM to only trace
> > > execution in specific code regions or to trace a few cycles every so
> > > often. In these cases, prev_packet->sample_type will not be zero, but
> > > whatever the previous packet was. You will get a CS_ETM_TRACE_ON packet in
> > > such cases, generated by an I_TRACE_ON element in the trace stream.
> > > You also get this on exception return.
> > >
> > > However, you should also keep the test for prev_packet->sample_type == 0
> > > as you may not see a CS_ETM_TRACE_ON when decoding a buffer that has
> > > wrapped.
> > Thanks for reviewing. Let's dig more detailed into this issue,
> > especially for handling packet CS_ETM_TRACE_ON, I'd like divide into two
> > sub cases.
> >
> > - The first case is for using python script:
> >
> > I use python script to analyze packets with below command:
> > ./perf script --itrace=ril128 -s arm-cs-trace-disasm.py -F cpu,event,ip,addr,sym -- -v -d objdump -k ./vmlinux
> >
> > What I observe is after we pass python script with parameter '-s
> > arm-cs-trace-disasm.py', then instruction tracing options
> > '--itrace=ril128' isn't really used; the perf tool creates another
> > new process for launch python script and re-enter cmd_script()
> > function, but at the second time when invoke cmd_script() for python
> > script execution the option '--itrace=ril128' is dropped and all
> > parameters are only valid defined by the python script.
> >
> > As result, I can the variable 'etmq->etm->synth_opts.last_branch' is
> > always FALSE for running python script. So all CS_ETM_TRACE_ON
> > packets will be ignored in the function cs_etm__flush().
> >
> > Even the CS_ETM_TRACE_ON packets are missed to handle, the program
> > flow still can work well. The reason is without the interference by
> > CS_ETM_TRACE_ON, the CS_ETM_RANGE packets can smoothly create
> > instruction range by ignore the middle CS_ETM_TRACE_ON packet.
> >
> > Please see below example, in this example there have 3 packets, the
> > first one packet is CS_ETM_RANGE packet which is labelled with
> > 'PACKET_1', the first one packet can properly generate branch sample
> > data with previous packet as expected; the second packet is
> > PACKET_2 which is CS_ETM_TRACE_ON, but
> > 'etmq->etm->synth_opts.last_branch' is false so function
> > cs_etm__flush() doesn't handle it and skip the swap operation
> > "etmq->prev_packet = tmp"; the third packet is PACKET_3, which is
> > CS_ETM_RANGE packet and we can see it's smoontly to create
> > continous instruction range between PACKET_1 and PACKET_3.
> >
> > cs_etm__sample: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f79c end_addr=0xffff000008a5f7bc last_instr_taken_branch=1
> > PACKET_1: cs_etm__sample: packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> > cs_etm__synth_branch_sample: ip=0xffff000008a5f7b8 addr=0xffff000008a5f858 pid=2290 tid=2290 id=1000000021 stream_id=1000000021 period=1 cpu=1 flags=0 cpumode=2
> >
> > cs_etm__flush: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> > PACKET_2: cs_etm__flush: packet: sample_type=2 exc=0 exc_ret=0 cpu=2 start_addr=0xdeadbeefdeadbeef end_addr=0xdeadbeefdeadbeef last_instr_taken_branch=1
> >
> > cs_etm__sample: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> > PACKET_3: cs_etm__sample: packet: sample_type=1 exc=0 exc_ret=0 cpu=2 start_addr=0xffff000008be7528 end_addr=0xffff000008be7538 last_instr_taken_branch=1
> > cs_etm__synth_branch_sample: ip=0xffff000008a5f860 addr=0xffff000008be7528 pid=2290 tid=2290 id=1000000021 stream_id=1000000021 period=1 cpu=2 flags=0 cpumode=2
> >
> > So seems to me, the CS_ETM_TRACE_ON packet doesn't introduce trouble
> > for the program flow analysis if we can handle all CS_ETM_RANGE
> > packets and without handling CS_ETM_TRACE_ON packet for branch
> > samples.
> >
> > - The second case is for --itrace option without python script:
> > ./perf script --itrace=ril -F cpu,event,ip,addr,sym -k ./vmlinux
> >
> > In this case, the flag 'etmq->etm->synth_opts.last_branch' is true
> > so CS_ETM_TRACE_ON packet will be handled; but I can observe the
> > CS_ETM_RANGE packet in etmq->prev_packet isn't handled in the
> > function cs_etm__flush() for branch sample, so actually we miss some
> > branch sample for this case.
> >
> > So I think we also need handle CS_ETM_RANGE packet in function
> > cs_etm__flush() to generate branch samples. But this has side
> > effect, we introduce the extra track for CS_ETM_TRACE_ON packet for
> > branch samples, so we will see one branch range like:
> > [ 0xdeadbeefdeadbeef .. 0xdeadbeefdeadbeef ].
> >
> > Please reivew below change is okay for you? Thanks a lot for
> > suggestions.
> >
> > diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> > index 822ba91..37d3722 100644
> > --- a/tools/perf/util/cs-etm.c
> > +++ b/tools/perf/util/cs-etm.c
> > @@ -495,6 +495,13 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
> > static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
> > {
> > /*
> > + * The packet is the start tracing packet if the end_addr is zero,
> > + * returns 0 for this case.
> > + */
> > + if (!packet->end_addr)
> > + return 0;
> > +
> > + /*
> > * The packet records the execution range with an exclusive end address
> > *
> > * A64 instructions are constant size, so the last executed
> > @@ -897,13 +904,28 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> > etmq->period_instructions = instrs_over;
> > }
> > - if (etm->sample_branches &&
> > - etmq->prev_packet &&
> > - etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> > - etmq->prev_packet->last_instr_taken_branch) {
> > - ret = cs_etm__synth_branch_sample(etmq);
> > - if (ret)
> > - return ret;
> > + if (etm->sample_branches && etmq->prev_packet) {
> > + bool generate_sample = false;
> > +
> > + /* Generate sample for start tracing packet */
> > + if (etmq->prev_packet->sample_type == 0 ||
> > + etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
> > + generate_sample = true;
> > +
> > + /* Generate sample for exception packet */
> > + if (etmq->prev_packet->exc == true)
> > + generate_sample = true;
> > +
> > + /* Generate sample for normal branch packet */
> > + if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> > + etmq->prev_packet->last_instr_taken_branch)
> > + generate_sample = true;
> > +
> > + if (generate_sample) {
> > + ret = cs_etm__synth_branch_sample(etmq);
> > + if (ret)
> > + return ret;
> > + }
> > }
> > if (etm->sample_branches || etm->synth_opts.last_branch) {
> > @@ -921,12 +943,17 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> > static int cs_etm__flush(struct cs_etm_queue *etmq)
> > {
> > + struct cs_etm_auxtrace *etm = etmq->etm;
> > int err = 0;
> > struct cs_etm_packet *tmp;
> > - if (etmq->etm->synth_opts.last_branch &&
> > - etmq->prev_packet &&
> > - etmq->prev_packet->sample_type == CS_ETM_RANGE) {
> > + if (!etmq->prev_packet)
> > + return 0;
> > +
> > + if (etmq->prev_packet->sample_type != CS_ETM_RANGE)
> > + return 0;
> > +
> > + if (etmq->etm->synth_opts.last_branch) {
> > /*
> > * Generate a last branch event for the branches left in the
> > * circular buffer at the end of the trace.
> > @@ -939,18 +966,25 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
> > err = cs_etm__synth_instruction_sample(
> > etmq, addr,
> > etmq->period_instructions);
> > + if (err)
> > + return err;
> > etmq->period_instructions = 0;
> > + }
> > - /*
> > - * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> > - * the next incoming packet.
> > - */
> > - tmp = etmq->packet;
> > - etmq->packet = etmq->prev_packet;
> > - etmq->prev_packet = tmp;
> > + if (etm->sample_branches) {
> > + err = cs_etm__synth_branch_sample(etmq);
> > + if (err)
> > + return err;
> > }
> > - return err;
> > + /*
> > + * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> > + * the next incoming packet.
> > + */
> > + tmp = etmq->packet;
> > + etmq->packet = etmq->prev_packet;
> > + etmq->prev_packet = tmp;
> > + return 0;
> > }
> > static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
^ permalink raw reply
* [PATCHv4 1/2] ARM: imx53: add secure-reg-access support for PMU
From: Sebastian Reichel @ 2018-05-25 15:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180227101712.3zwobvs4ox4jchcj@earth.universe>
Hi Shawn,
On Tue, Feb 27, 2018 at 11:17:12AM +0100, Sebastian Reichel wrote:
> Hi,
>
> On Tue, Feb 27, 2018 at 09:10:34AM +0800, Shawn Guo wrote:
> > On Mon, Feb 26, 2018 at 02:47:41PM +0100, Sebastian Reichel wrote:
> > > On Sat, Feb 24, 2018 at 03:45:44PM +0800, Shawn Guo wrote:
> > > > On Mon, Feb 12, 2018 at 01:39:44PM +0100, Sebastian Reichel wrote:
> > > > > On i.MX53 it is necessary to set the DBG_EN bit in the
> > > > > platform GPC register to enable access to PMU counters
> > > > > other than the cycle counter.
> > > > >
> > > > > Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
> > > > > ---
> > > > > arch/arm/mach-imx/mach-imx53.c | 39 ++++++++++++++++++++++++++++++++++++++-
> > > > > 1 file changed, 38 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
> > > > > index 07c2e8dca494..658e28604dca 100644
> > > > > --- a/arch/arm/mach-imx/mach-imx53.c
> > > > > +++ b/arch/arm/mach-imx/mach-imx53.c
> > > > > @@ -28,10 +28,47 @@ static void __init imx53_init_early(void)
> > > > > mxc_set_cpu_type(MXC_CPU_MX53);
> > > > > }
> > > > >
> > > > > +#define MXC_CORTEXA8_PLAT_GPC 0x63fa0004
> > > >
> > > > The base address should be retrieved from device tree.
> > >
> > > DT has no entry for 0x63fa0000-0x63fa3fff. iMX53 TRM lists it as "ARM Platform"
> > > with 8 platform specific 32 bit registers. Do you think it's worth the trouble
> > > adding a new binding? Do you have a suggestion for a compatible value?
> >
> > Looking at it more closely, I feel that patching every single platform
> > which needs to set up additional register for secure-reg-access support
> > doesn't really scale. Can we have pmu driver do it with a phandle in
> > DT pointing to the register and bit that need to be configured?
>
> The PMU driver used to have a feature for initialising platform
> specific bits, but it is currently being removed to make the PMU
> code more maintainable. My understanding is, that it's very uncommon
> to require platform specific setup to get secure-reg-access working.
> E.g. it is not needed for newer iMX platforms.
You never replied to this one. Are you fine with adding the
function? This is kind of a deadlock situation with neither
you wanting to enable the platform bit, nor the generic PMU
driver.
-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180525/431c48ca/attachment.sig>
^ permalink raw reply
* [PATCH v3 08/15] ARM: spectre-v2: harden user aborts in kernel space
From: Tony Lindgren @ 2018-05-25 15:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <E1fMDHD-00073Q-Ob@rmk-PC.armlinux.org.uk>
* Russell King <rmk+kernel@armlinux.org.uk> [180525 15:10]:
> +static void cpu_v7_spectre_init(void)
> +{
> + const char *spectre_v2_method = NULL;
> + int cpu = smp_processor_id();
> +
> + if (per_cpu(harden_branch_predictor_fn, cpu))
> + return;
> +
> + switch (read_cpuid_part()) {
> + case ARM_CPU_PART_CORTEX_A8:
> + case ARM_CPU_PART_CORTEX_A9:
> + case ARM_CPU_PART_CORTEX_A12:
> + case ARM_CPU_PART_CORTEX_A17:
> + case ARM_CPU_PART_CORTEX_A73:
> + case ARM_CPU_PART_CORTEX_A75:
> + per_cpu(harden_branch_predictor_fn, cpu) =
> + harden_branch_predictor_bpiall;
> + spectre_v2_method = "BPIALL";
> + break;
> +
> + case ARM_CPU_PART_CORTEX_A15:
> + case ARM_CPU_PART_BRAHMA_B15:
> + per_cpu(harden_branch_predictor_fn, cpu) =
> + harden_branch_predictor_iciallu;
> + spectre_v2_method = "ICIALLU";
> + break;
> + }
> + if (spectre_v2_method)
> + pr_info("CPU%u: Spectre v2: using %s workaround\n",
> + smp_processor_id(), spectre_v2_method);
> +}
We can now get this with the whole series applied:
CPU0: Spectre v2: firmware did not set auxiliary control register
IBE bit, system vulnerable
CPU: Spectre v2: using ICIALLU workaround
So maybe change the wording from "using %s workaround" to
"chosen workaround %s"?
Or I guess disabling the pr_info when not functional can
be done in the later patches based on some variable set
by check_spectre_auxcr() would be doable too.
Regards,
Tony
^ permalink raw reply
* [PATCH 1/8] drm/sun4i: mark PM functions as __maybe_unused
From: Arnd Bergmann @ 2018-05-25 15:50 UTC (permalink / raw)
To: linux-arm-kernel
Disabling CONFIG_PM produces a compile time warning when these
functions are not referenced:
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c:1072:12: error: 'sun6i_dsi_runtime_suspend' defined but not used [-Werror=unused-function]
static int sun6i_dsi_runtime_suspend(struct device *dev)
^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c:1043:12: error: 'sun6i_dsi_runtime_resume' defined but not used [-Werror=unused-function]
static int sun6i_dsi_runtime_resume(struct device *dev)
^~~~~~~~~~~~~~~~~~~~~~~~
Fixes: 133add5b5ad4 ("drm/sun4i: Add Allwinner A31 MIPI-DSI controller support")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index bfbf761f0c1d..d4e7d16a2514 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1040,7 +1040,7 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
return 0;
}
-static int sun6i_dsi_runtime_resume(struct device *dev)
+static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
{
struct sun6i_dsi *dsi = dev_get_drvdata(dev);
@@ -1069,7 +1069,7 @@ static int sun6i_dsi_runtime_resume(struct device *dev)
return 0;
}
-static int sun6i_dsi_runtime_suspend(struct device *dev)
+static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)
{
struct sun6i_dsi *dsi = dev_get_drvdata(dev);
--
2.9.0
^ permalink raw reply related
* [PATCH 6/8] drm/exynos: fix scaler_task_done return type
From: Arnd Bergmann @ 2018-05-25 15:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525155030.3667352-1-arnd@arndb.de>
Modern gcc versions warn about returning a ternary operator with an 'int'
type in a function returning type 'bool':
drivers/gpu/drm/exynos/exynos_drm_scaler.c: In function 'scaler_task_done':
drivers/gpu/drm/exynos/exynos_drm_scaler.c:402:47: error: ?: using integer constants in boolean context [-Werror=int-in-bool-context]
return val & SCALER_INT_STATUS_FRAME_END ? 0 : -EINVAL;
>From context, it becomes clear that this should have been 'int',
so I'm fixing it, along with parenthesizing the expression to make
it clearer what is meant here (I got confused at first, after seeing
the warning).
Fixes: 01fb9185dc18 ("drm/exynos: Add driver for Exynos Scaler module")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/gpu/drm/exynos/exynos_drm_scaler.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
index 63b05b7c846a..4ad49d7782cd 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -397,9 +397,9 @@ static inline u32 scaler_get_int_status(struct scaler_context *scaler)
return scaler_read(SCALER_INT_STATUS);
}
-static inline bool scaler_task_done(u32 val)
+static inline int scaler_task_done(u32 val)
{
- return val & SCALER_INT_STATUS_FRAME_END ? 0 : -EINVAL;
+ return (val & SCALER_INT_STATUS_FRAME_END) ? 0 : -EINVAL;
}
static irqreturn_t scaler_irq_handler(int irq, void *arg)
--
2.9.0
^ permalink raw reply related
* [PATCH v3 08/15] ARM: spectre-v2: harden user aborts in kernel space
From: Russell King - ARM Linux @ 2018-05-25 15:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525154742.GA77025@atomide.com>
On Fri, May 25, 2018 at 08:47:42AM -0700, Tony Lindgren wrote:
> * Russell King <rmk+kernel@armlinux.org.uk> [180525 15:10]:
> > +static void cpu_v7_spectre_init(void)
> > +{
> > + const char *spectre_v2_method = NULL;
> > + int cpu = smp_processor_id();
> > +
> > + if (per_cpu(harden_branch_predictor_fn, cpu))
> > + return;
> > +
> > + switch (read_cpuid_part()) {
> > + case ARM_CPU_PART_CORTEX_A8:
> > + case ARM_CPU_PART_CORTEX_A9:
> > + case ARM_CPU_PART_CORTEX_A12:
> > + case ARM_CPU_PART_CORTEX_A17:
> > + case ARM_CPU_PART_CORTEX_A73:
> > + case ARM_CPU_PART_CORTEX_A75:
> > + per_cpu(harden_branch_predictor_fn, cpu) =
> > + harden_branch_predictor_bpiall;
> > + spectre_v2_method = "BPIALL";
> > + break;
> > +
> > + case ARM_CPU_PART_CORTEX_A15:
> > + case ARM_CPU_PART_BRAHMA_B15:
> > + per_cpu(harden_branch_predictor_fn, cpu) =
> > + harden_branch_predictor_iciallu;
> > + spectre_v2_method = "ICIALLU";
> > + break;
> > + }
> > + if (spectre_v2_method)
> > + pr_info("CPU%u: Spectre v2: using %s workaround\n",
> > + smp_processor_id(), spectre_v2_method);
> > +}
>
> We can now get this with the whole series applied:
>
> CPU0: Spectre v2: firmware did not set auxiliary control register
> IBE bit, system vulnerable
> CPU: Spectre v2: using ICIALLU workaround
>
> So maybe change the wording from "using %s workaround" to
> "chosen workaround %s"?
>
> Or I guess disabling the pr_info when not functional can
> be done in the later patches based on some variable set
> by check_spectre_auxcr() would be doable too.
You should not be getting both messages. It looks like you're using
an older series - I assumed you pulled my git tree rather than the
patches? The public git tree isn't up to date with these changes.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH v2 1/3] input: touchscreen: edt-ft5x06: don't make device a wakeup source by default
From: Rob Herring @ 2018-05-25 15:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524231732.GC177107@dtor-ws>
On Thu, May 24, 2018 at 6:17 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Wed, May 23, 2018 at 09:45:05AM -0500, Rob Herring wrote:
>> On Wed, May 23, 2018 at 3:27 AM, Daniel Mack <daniel@zonque.org> wrote:
>> > On Tuesday, May 22, 2018 07:54 PM, Rob Herring wrote:
>> >>
>> >> On Thu, May 17, 2018 at 11:05:50AM +0200, Daniel Mack wrote:
>> >>>
>> >>> Allow configuring the device as wakeup source through device properties,
>> >>> as
>> >>> not all platforms want to wake up on touch screen activity.
>> >>>
>> >>> The I2C core automatically reads the "wakeup-source" DT property to
>> >>> configure a device's wakeup capability, and board supports files can set
>> >>> I2C_CLIENT_WAKE in the flags.
>> >>
>> >>
>> >> This will break wake-up on working systems. Looks like mostly i.MX, but
>> >> there's one AM437x board. If that board doesn't care, then it is up to
>> >> Shawn.
>> >
>> >
>> > I added the property to the dts files, but as Dmitry pointed out, I missed
>> > some. Sorry for that.
>>
>> Just adding the property to dts files doesn't fix the compatibility
>> problem. If a user uses an existing dtb (before this change) with a
>> new kernel (after this change), then wakeup will stop working.
>
> Is this a practical problem though? Do we know of any products with
> this touch panel that use DTS not distributed with the kernel?
Distribution of dts with kernel is irrelevant. It is how the dtb's are
handled that matters. You still need to ask in tree users.
I can't have any way of knowing what DTs may exist as there is only
one upstream repository of dts files. There's not really a good
solution on this to avoid breaking users, so we'll just have to see if
anyone (besides the known users) complains.
Rob
^ permalink raw reply
* [RFT v2 1/4] perf cs-etm: Generate sample for missed packets
From: Leo Yan @ 2018-05-25 15:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525152713.GD4091@kernel.org>
Hi Arnaldo, Rob,
On Fri, May 25, 2018 at 12:27:13PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Fri, May 25, 2018 at 03:03:47PM +0100, Robert Walker escreveu:
> > Hi Leo,
> >
> > Following the discussions from your reply to this with a simplified patch,
> > this version of the patch works better as you also need to emit a branch
> > sample when handling a CS_ETM_TRACE_ON packet to indicate the end of a block
> > of trace.
I also will follow the suggestion as Rob mentioned in another email:
"The deadbeefdeadbeef addresses are a bit ugly - these are just dummy
values emitted in the decoder layer - maybe these should be changed
to 0."
> > This patch does not break the output from perf inject to generate
> > instruction samples for AutoFDO, so I am happy with that.
Thanks for confirmation.
> > Regards
> >
> > Rob
> >
> > Reviewed-by: Robert Walker <robert.walker@arm.com>
>
> So, Leo, can you please resubmit, bumping the v2 to v3 (or the latest
> one, I haven't fully reread this thread) add this "Reviewed-by: Robert"
> tag and any other that people may have provided, so that I can merge it?
Sure! I will respin the v3 patch series by following up Rob's
suggestion and add Rob's review tag.
BTW, I'd like to get ack from Mathieu as well. Mathieu is working on
CPU wide tracing, so I talked with Mathieu he will review the patch
series if has conflict with CPU wide tracing.
[...]
Thanks,
Leo Yan
^ permalink raw reply
* [PATCH v3 08/15] ARM: spectre-v2: harden user aborts in kernel space
From: Tony Lindgren @ 2018-05-25 16:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525155207.GF17671@n2100.armlinux.org.uk>
* Russell King - ARM Linux <linux@armlinux.org.uk> [180525 15:54]:
> On Fri, May 25, 2018 at 08:47:42AM -0700, Tony Lindgren wrote:
> > We can now get this with the whole series applied:
> >
> > CPU0: Spectre v2: firmware did not set auxiliary control register
> > IBE bit, system vulnerable
> > CPU: Spectre v2: using ICIALLU workaround
> >
> > So maybe change the wording from "using %s workaround" to
> > "chosen workaround %s"?
> >
> > Or I guess disabling the pr_info when not functional can
> > be done in the later patches based on some variable set
> > by check_spectre_auxcr() would be doable too.
>
> You should not be getting both messages. It looks like you're using
> an older series - I assumed you pulled my git tree rather than the
> patches? The public git tree isn't up to date with these changes.
Yes I just fetched your git tree because it allows using
git mergetool because of the conflicts with next. I'll apply
manually and test again.
Thanks,
Tony
^ permalink raw reply
* [GIT PULL] arm64: fixes for -rc7
From: Will Deacon @ 2018-05-25 16:04 UTC (permalink / raw)
To: linux-arm-kernel
Hi Linus,
Here are a few arm64 fixes for -rc7. The two main fixes are for the asm
constraints in our LSE atomics and for our pmd/pud setters when changing
permissions for kernel mappings. Summary in the tag.
Please pull,
Will
--->8
The following changes since commit 771c577c23bac90597c685971d7297ea00f99d11:
Linux 4.17-rc6 (2018-05-20 15:31:38 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-fixes
for you to fetch changes up to 82034c23fcbc2389c73d97737f61fa2dd6526413:
arm64: Make sure permission updates happen for pmd/pud (2018-05-24 11:19:31 +0100)
----------------------------------------------------------------
More arm64 fixes:
- Fix application of read-only permissions to kernel section mappings
- Sanitise reported ESR values for signals delivered on a kernel address
- Ensure tishift GCC helpers are exported to modules
- Fix inline asm constraints for some LSE atomics
----------------------------------------------------------------
Jason A. Donenfeld (1):
arm64: export tishift functions to modules
Laura Abbott (1):
arm64: Make sure permission updates happen for pmd/pud
Peter Maydell (1):
arm64: fault: Don't leak data in ESR context for user fault on kernel VA
Will Deacon (1):
arm64: lse: Add early clobbers to some input/output asm operands
arch/arm64/include/asm/atomic_lse.h | 24 ++++++++---------
arch/arm64/kernel/arm64ksyms.c | 8 ++++++
arch/arm64/lib/tishift.S | 15 ++---------
arch/arm64/mm/fault.c | 51 +++++++++++++++++++++++++++++++++++++
arch/arm64/mm/mmu.c | 16 +++++++-----
5 files changed, 83 insertions(+), 31 deletions(-)
^ permalink raw reply
* [PATCH v1 1/4] soc: Add TmFifo driver for Mellanox BlueField Soc
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds the TmFifo driver for Mellanox BlueField Soc.
TmFifo is a shared FIFO which enables external host machine to
exchange data with the SoC via USB or PCIe. The driver is based on
virtio framework and has console and network access enabled.
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/mellanox/Kconfig | 18 +
drivers/soc/mellanox/Makefile | 5 +
drivers/soc/mellanox/tmfifo.c | 1265 ++++++++++++++++++++++++++++++++++++
drivers/soc/mellanox/tmfifo_regs.h | 112 ++++
6 files changed, 1402 insertions(+)
create mode 100644 drivers/soc/mellanox/Kconfig
create mode 100644 drivers/soc/mellanox/Makefile
create mode 100644 drivers/soc/mellanox/tmfifo.c
create mode 100644 drivers/soc/mellanox/tmfifo_regs.h
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index c07b4a8..fa87dc8 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -7,6 +7,7 @@ source "drivers/soc/bcm/Kconfig"
source "drivers/soc/fsl/Kconfig"
source "drivers/soc/imx/Kconfig"
source "drivers/soc/mediatek/Kconfig"
+source "drivers/soc/mellanox/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 4052357..868163f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_GEMINI) += gemini/
obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_SOC_XWAY) += lantiq/
obj-y += mediatek/
+obj-$(CONFIG_SOC_MLNX) += mellanox/
obj-$(CONFIG_ARCH_MESON) += amlogic/
obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-y += renesas/
diff --git a/drivers/soc/mellanox/Kconfig b/drivers/soc/mellanox/Kconfig
new file mode 100644
index 0000000..d88efa1
--- /dev/null
+++ b/drivers/soc/mellanox/Kconfig
@@ -0,0 +1,18 @@
+menuconfig SOC_MLNX
+ bool "Mellanox SoC drivers"
+ default y if ARCH_MLNX_BLUEFIELD
+
+if ARCH_MLNX_BLUEFIELD || COMPILE_TEST
+
+config MLNX_BLUEFIELD_TMFIFO
+ tristate "Mellanox BlueField SoC TmFifo driver"
+ depends on ARM64
+ default m
+ select VIRTIO_CONSOLE
+ select VIRTIO_NET
+ help
+ Say y here to enable TmFifo support. The TmFifo driver provides the
+ virtio driver framework for the TMFIFO of Mellanox BlueField SoC and
+ the implementation of a console and network driver.
+
+endif # ARCH_MLNX_BLUEFIELD
diff --git a/drivers/soc/mellanox/Makefile b/drivers/soc/mellanox/Makefile
new file mode 100644
index 0000000..c44c0e2
--- /dev/null
+++ b/drivers/soc/mellanox/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Mellanox SoC drivers.
+#
+obj-$(CONFIG_MLNX_BLUEFIELD_TMFIFO) += tmfifo.o
diff --git a/drivers/soc/mellanox/tmfifo.c b/drivers/soc/mellanox/tmfifo.c
new file mode 100644
index 0000000..a3303d1
--- /dev/null
+++ b/drivers/soc/mellanox/tmfifo.c
@@ -0,0 +1,1265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/acpi.h>
+#include <linux/cache.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/efi.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_console.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_ring.h>
+#include <asm/byteorder.h>
+
+#include "tmfifo_regs.h"
+
+/* Several utility macros to get/set the register fields. */
+#define TMFIFO_GET_FIELD(reg, field) \
+ (((reg) >> field##_SHIFT) & ((1UL << field##_WIDTH) - 1))
+
+#define TMFIFO_SET_FIELD(reg, field, value) ({ \
+ u64 _mask = ((1UL << field##_WIDTH) - 1) << field##_SHIFT; \
+ ((reg) & ~_mask) | (((value) << field##_SHIFT) & _mask); \
+})
+
+#define TMFIFO_RX_GET_STS_CNT(sts) \
+ TMFIFO_GET_FIELD(sts, TMFIFO_RX_STS__COUNT)
+
+#define TMFIFO_TX_GET_STS_CNT(sts) \
+ TMFIFO_GET_FIELD(sts, TMFIFO_TX_STS__COUNT)
+
+/* Vring size. */
+#define TMFIFO_VRING_SIZE 1024
+
+/* Console Tx buffer size. */
+#define TMFIFO_CONS_TX_BUF_SIZE (32 * 1024)
+
+/* Use a timer for house-keeping. */
+static int tmfifo_timer_interval = HZ / 10;
+
+/* Global lock. */
+static struct mutex tmfifo_lock;
+
+/* Virtio ring size. */
+static int tmfifo_vring_size = TMFIFO_VRING_SIZE;
+module_param(tmfifo_vring_size, int, 0444);
+MODULE_PARM_DESC(tmfifo_vring_size, "Size of the vring.");
+
+struct tmfifo;
+
+/* A flag to indicate TmFifo ready. */
+static bool tmfifo_ready;
+
+/* Virtual devices sharing the TM FIFO. */
+#define TMFIFO_VDEV_MAX (VIRTIO_ID_CONSOLE + 1)
+
+/* Spin lock. */
+static DEFINE_SPINLOCK(tmfifo_spin_lock);
+
+/* Structure to maintain the ring state. */
+struct tmfifo_vring {
+ void *va; /* virtual address */
+ dma_addr_t dma; /* dma address */
+ struct virtqueue *vq; /* virtqueue pointer */
+ struct vring_desc *desc; /* current desc */
+ struct vring_desc *desc_head; /* current desc head */
+ int cur_len; /* processed len in current desc */
+ int rem_len; /* remaining length to be processed */
+ int size; /* vring size */
+ int align; /* vring alignment */
+ int id; /* vring id */
+ int vdev_id; /* TMFIFO_VDEV_xxx */
+ u32 pkt_len; /* packet total length */
+ __virtio16 next_avail; /* next avail desc id */
+ struct tmfifo *fifo; /* pointer back to the tmfifo */
+};
+
+/* Interrupt types. */
+enum {
+ TM_RX_LWM_IRQ, /* Rx low water mark irq */
+ TM_RX_HWM_IRQ, /* Rx high water mark irq */
+ TM_TX_LWM_IRQ, /* Tx low water mark irq */
+ TM_TX_HWM_IRQ, /* Tx high water mark irq */
+ TM_IRQ_CNT
+};
+
+/* Ring types (Rx & Tx). */
+enum {
+ TMFIFO_VRING_RX, /* Rx ring */
+ TMFIFO_VRING_TX, /* Tx ring */
+ TMFIFO_VRING_NUM
+};
+
+struct tmfifo_vdev {
+ struct virtio_device vdev; /* virtual device */
+ u8 status;
+ u64 features;
+ union { /* virtio config space */
+ struct virtio_console_config cons;
+ struct virtio_net_config net;
+ } config;
+ struct tmfifo_vring vrings[TMFIFO_VRING_NUM];
+ u8 *tx_buf; /* tx buffer */
+ u32 tx_head; /* tx buffer head */
+ u32 tx_tail; /* tx buffer tail */
+};
+
+#define TMFIFO_VDEV_TX_BUF_AVAIL(vdev) \
+ (((vdev)->tx_tail >= (vdev)->tx_head) ? \
+ (TMFIFO_CONS_TX_BUF_SIZE - 8 - ((vdev)->tx_tail - (vdev)->tx_head)) : \
+ ((vdev)->tx_head - (vdev)->tx_tail - 8))
+
+#define TMFIFO_VDEV_TX_BUF_PUSH(vdev, len) do { \
+ (vdev)->tx_tail += (len); \
+ if ((vdev)->tx_tail >= TMFIFO_CONS_TX_BUF_SIZE) \
+ (vdev)->tx_tail -= TMFIFO_CONS_TX_BUF_SIZE; \
+} while (0)
+
+#define TMFIFO_VDEV_TX_BUF_POP(vdev, len) do { \
+ (vdev)->tx_head += (len); \
+ if ((vdev)->tx_head >= TMFIFO_CONS_TX_BUF_SIZE) \
+ (vdev)->tx_head -= TMFIFO_CONS_TX_BUF_SIZE; \
+} while (0)
+
+/* TMFIFO device structure */
+struct tmfifo {
+ struct tmfifo_vdev *vdev[TMFIFO_VDEV_MAX]; /* virtual devices */
+ struct platform_device *pdev; /* platform device */
+ struct mutex lock;
+ void __iomem *rx_base; /* mapped register base */
+ void __iomem *tx_base; /* mapped register base */
+ int tx_fifo_size; /* number of entries of the Tx FIFO */
+ int rx_fifo_size; /* number of entries of the Rx FIFO */
+ unsigned long pend_events; /* pending bits for deferred process */
+ int irq[TM_IRQ_CNT]; /* irq numbers */
+ struct work_struct work; /* work struct for deferred process */
+ struct timer_list timer; /* keepalive timer */
+ struct tmfifo_vring *vring[2]; /* current Tx/Rx ring */
+};
+
+union tmfifo_msg_hdr {
+ struct {
+ u8 type; /* message type */
+ __be16 len; /* payload length */
+ u8 unused[5]; /* reserved, set to 0 */
+ } __packed;
+ u64 data;
+};
+
+/*
+ * Default MAC.
+ * This MAC address will be read from EFI persistent variable if configured.
+ * It can also be reconfigured with standard Linux tools.
+ */
+static u8 tmfifo_net_default_mac[6] = {0x00, 0x1A, 0xCA, 0xFF, 0xFF, 0x01};
+
+/* MTU setting of the virtio-net interface. */
+#define TMFIFO_NET_MTU 1500
+
+/* Supported virtio-net features. */
+#define TMFIFO_NET_FEATURES ((1UL << VIRTIO_NET_F_MTU) | \
+ (1UL << VIRTIO_NET_F_STATUS) | \
+ (1UL << VIRTIO_NET_F_MAC))
+
+/* Forward declaration. */
+static void tmfifo_virtio_rxtx(struct virtqueue *vq, bool is_rx);
+static void tmfifo_release_pkt(struct virtio_device *vdev,
+ struct tmfifo_vring *vring,
+ struct vring_desc **desc);
+
+/* Allocate vrings for the fifo. */
+static int tmfifo_alloc_vrings(struct tmfifo *fifo,
+ struct tmfifo_vdev *tm_vdev, int vdev_id)
+{
+ dma_addr_t dma;
+ void *va;
+ int i, size;
+ struct tmfifo_vring *vring;
+
+ for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+ vring = &tm_vdev->vrings[i];
+ vring->fifo = fifo;
+ vring->size = tmfifo_vring_size;
+ vring->align = SMP_CACHE_BYTES;
+ vring->id = i;
+ vring->vdev_id = vdev_id;
+
+ size = PAGE_ALIGN(vring_size(vring->size, vring->align));
+ va = dma_alloc_coherent(tm_vdev->vdev.dev.parent, size, &dma,
+ GFP_KERNEL);
+ if (!va) {
+ dev_err(tm_vdev->vdev.dev.parent,
+ "vring allocation failed\n");
+ return -EINVAL;
+ }
+
+ vring->va = va;
+ vring->dma = dma;
+ }
+
+ return 0;
+}
+
+/* Free vrings of the fifo device. */
+static void tmfifo_free_vrings(struct tmfifo *fifo, int vdev_id)
+{
+ int i, size;
+ struct tmfifo_vring *vring;
+ struct tmfifo_vdev *tm_vdev = fifo->vdev[vdev_id];
+
+ for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+ vring = &tm_vdev->vrings[i];
+
+ size = PAGE_ALIGN(vring_size(vring->size, vring->align));
+ if (vring->va) {
+ dma_free_coherent(tm_vdev->vdev.dev.parent, size,
+ vring->va, vring->dma);
+ vring->va = NULL;
+ if (vring->vq) {
+ vring_del_virtqueue(vring->vq);
+ vring->vq = NULL;
+ }
+ }
+ }
+}
+
+/* Free interrupts of the fifo device. */
+static void tmfifo_free_irqs(struct tmfifo *fifo)
+{
+ int i, irq;
+
+ for (i = 0; i < TM_IRQ_CNT; i++) {
+ irq = fifo->irq[i];
+ if (irq) {
+ fifo->irq[i] = 0;
+ disable_irq(irq);
+ free_irq(irq, (u8 *)fifo + i);
+ }
+ }
+}
+
+/* Work handler for Rx, Tx or activity monitoring. */
+static void tmfifo_work_handler(struct work_struct *work)
+{
+ int i;
+ struct tmfifo_vdev *tm_vdev;
+ struct tmfifo *fifo = container_of(work, struct tmfifo, work);
+
+ if (!tmfifo_ready)
+ return;
+
+ mutex_lock(&fifo->lock);
+
+ /* Tx. */
+ if (test_and_clear_bit(TM_TX_LWM_IRQ, &fifo->pend_events) &&
+ fifo->irq[TM_TX_LWM_IRQ]) {
+ for (i = 0; i < TMFIFO_VDEV_MAX; i++) {
+ tm_vdev = fifo->vdev[i];
+ if (tm_vdev != NULL) {
+ tmfifo_virtio_rxtx(
+ tm_vdev->vrings[TMFIFO_VRING_TX].vq,
+ false);
+ }
+ }
+ }
+
+ /* Rx. */
+ if (test_and_clear_bit(TM_RX_HWM_IRQ, &fifo->pend_events) &&
+ fifo->irq[TM_RX_HWM_IRQ]) {
+ for (i = 0; i < TMFIFO_VDEV_MAX; i++) {
+ tm_vdev = fifo->vdev[i];
+ if (tm_vdev != NULL) {
+ tmfifo_virtio_rxtx(
+ tm_vdev->vrings[TMFIFO_VRING_RX].vq,
+ true);
+ }
+ }
+ }
+
+ mutex_unlock(&fifo->lock);
+}
+
+/* Interrupt handler. */
+static irqreturn_t tmfifo_irq_handler(int irq, void *dev_id)
+{
+ int i = (uintptr_t)dev_id % sizeof(void *);
+ struct tmfifo *fifo = dev_id - i;
+
+ if (i < TM_IRQ_CNT && !test_and_set_bit(i, &fifo->pend_events))
+ schedule_work(&fifo->work);
+
+ return IRQ_HANDLED;
+}
+
+/* Nothing to do for now. */
+static void tmfifo_virtio_dev_release(struct device *dev)
+{
+}
+
+/* Get the next packet descriptor from the vring. */
+static inline struct vring_desc *
+tmfifo_virtio_get_next_desc(struct virtqueue *vq)
+{
+ unsigned int idx, head;
+ struct vring *vr = (struct vring *)virtqueue_get_vring(vq);
+ struct tmfifo_vring *vring = (struct tmfifo_vring *)vq->priv;
+
+ if (!vr || vring->next_avail == vr->avail->idx)
+ return NULL;
+
+ idx = vring->next_avail % vr->num;
+ head = vr->avail->ring[idx];
+ BUG_ON(head >= vr->num);
+ vring->next_avail++;
+ return &vr->desc[head];
+}
+
+static inline void tmfifo_virtio_release_desc(struct virtio_device *vdev,
+ struct vring *vr,
+ struct vring_desc *desc, u32 len)
+{
+ unsigned int idx;
+
+ idx = vr->used->idx % vr->num;
+ vr->used->ring[idx].id = desc - vr->desc;
+ vr->used->ring[idx].len = cpu_to_virtio32(vdev, len);
+
+ /* Virtio could poll and check the 'idx' to decide
+ * whether the desc is done or not. Add a memory
+ * barrier here to make sure the update above completes
+ * before updating the idx.
+ */
+ mb();
+ vr->used->idx++;
+}
+
+/* Get the total length of a descriptor chain. */
+static inline u32 tmfifo_virtio_get_pkt_len(struct virtio_device *vdev,
+ struct vring_desc *desc, struct vring *vr)
+{
+ u32 len = 0, idx;
+
+ while (desc) {
+ len += virtio32_to_cpu(vdev, desc->len);
+ if (!(virtio16_to_cpu(vdev, desc->flags) & VRING_DESC_F_NEXT))
+ break;
+ idx = virtio16_to_cpu(vdev, desc->next);
+ desc = &vr->desc[idx];
+ }
+
+ return len;
+}
+
+static void tmfifo_release_pkt(struct virtio_device *vdev,
+ struct tmfifo_vring *vring,
+ struct vring_desc **desc)
+{
+ struct vring *vr = (struct vring *)virtqueue_get_vring(vring->vq);
+ struct vring_desc *desc_head;
+ uint32_t pkt_len = 0;
+
+ if (!vr)
+ return;
+
+ if (desc != NULL && *desc != NULL && vring->desc_head != NULL) {
+ desc_head = vring->desc_head;
+ pkt_len = vring->pkt_len;
+ } else {
+ desc_head = tmfifo_virtio_get_next_desc(vring->vq);
+ if (desc_head != NULL) {
+ pkt_len = tmfifo_virtio_get_pkt_len(vdev,
+ desc_head, vr);
+ }
+ }
+
+ if (desc_head != NULL)
+ tmfifo_virtio_release_desc(vdev, vr, desc_head, pkt_len);
+
+ if (desc != NULL)
+ *desc = NULL;
+ vring->pkt_len = 0;
+}
+
+/* House-keeping timer. */
+static void tmfifo_timer(struct timer_list *arg)
+{
+ struct tmfifo *fifo = container_of(arg, struct tmfifo, timer);
+
+ /*
+ * Wake up the work handler to poll the Rx FIFO in case interrupt
+ * missing or any leftover bytes stuck in the FIFO.
+ */
+ test_and_set_bit(TM_RX_HWM_IRQ, &fifo->pend_events);
+
+ /*
+ * Wake up Tx handler in case virtio has queued too many packets
+ * and are waiting for buffer return.
+ */
+ test_and_set_bit(TM_TX_LWM_IRQ, &fifo->pend_events);
+
+ schedule_work(&fifo->work);
+
+ mod_timer(&fifo->timer, jiffies + tmfifo_timer_interval);
+}
+
+/* Buffer the console output. */
+static void tmfifo_console_output(struct tmfifo_vdev *cons,
+ struct virtqueue *vq)
+{
+ u32 len, pkt_len, idx;
+ struct vring_desc *head_desc, *desc = NULL;
+ struct vring *vr = (struct vring *)virtqueue_get_vring(vq);
+ struct virtio_device *vdev = &cons->vdev;
+ void *addr;
+ union tmfifo_msg_hdr *hdr;
+
+ for (;;) {
+ head_desc = tmfifo_virtio_get_next_desc(vq);
+ if (head_desc == NULL)
+ break;
+
+ /* Release the packet if no more space. */
+ pkt_len = tmfifo_virtio_get_pkt_len(vdev, head_desc, vr);
+ if (pkt_len + sizeof(*hdr) > TMFIFO_VDEV_TX_BUF_AVAIL(cons)) {
+ tmfifo_virtio_release_desc(vdev, vr, head_desc,
+ pkt_len);
+ break;
+ }
+
+ hdr = (union tmfifo_msg_hdr *)&cons->tx_buf[cons->tx_tail];
+ hdr->data = 0;
+ hdr->type = VIRTIO_ID_CONSOLE;
+ hdr->len = htons(pkt_len);
+
+ TMFIFO_VDEV_TX_BUF_PUSH(cons, sizeof(*hdr));
+ desc = head_desc;
+
+ while (desc != NULL) {
+ addr = phys_to_virt(virtio64_to_cpu(vdev, desc->addr));
+ len = virtio32_to_cpu(vdev, desc->len);
+
+ if (len <= TMFIFO_CONS_TX_BUF_SIZE - cons->tx_tail) {
+ memcpy(cons->tx_buf + cons->tx_tail, addr, len);
+ } else {
+ u32 seg;
+
+ seg = TMFIFO_CONS_TX_BUF_SIZE - cons->tx_tail;
+ memcpy(cons->tx_buf + cons->tx_tail, addr, seg);
+ addr += seg;
+ memcpy(cons->tx_buf, addr, len - seg);
+ }
+ TMFIFO_VDEV_TX_BUF_PUSH(cons, len);
+
+ if (!(virtio16_to_cpu(vdev, desc->flags) &
+ VRING_DESC_F_NEXT))
+ break;
+ idx = virtio16_to_cpu(vdev, desc->next);
+ desc = &vr->desc[idx];
+ }
+
+ /* Make each packet 8-byte aligned. */
+ TMFIFO_VDEV_TX_BUF_PUSH(cons, ((pkt_len + 7) & -8) - pkt_len);
+
+ tmfifo_virtio_release_desc(vdev, vr, head_desc, pkt_len);
+ }
+}
+
+/* Rx & Tx processing of a virtual queue. */
+static void tmfifo_virtio_rxtx(struct virtqueue *vq, bool is_rx)
+{
+ struct tmfifo_vring *vring;
+ struct tmfifo *fifo;
+ struct vring *vr;
+ struct virtio_device *vdev;
+ u64 sts, data;
+ int num_avail = 0, hdr_len, tx_reserve;
+ void *addr;
+ u32 len, idx;
+ struct vring_desc *desc;
+ unsigned long flags;
+ struct tmfifo_vdev *cons;
+
+ if (!vq)
+ return;
+
+ vring = (struct tmfifo_vring *)vq->priv;
+ fifo = vring->fifo;
+ vr = (struct vring *)virtqueue_get_vring(vq);
+
+ if (!fifo->vdev[vring->vdev_id])
+ return;
+ vdev = &fifo->vdev[vring->vdev_id]->vdev;
+ cons = fifo->vdev[VIRTIO_ID_CONSOLE];
+
+ /* Don't continue if another vring is running. */
+ if (fifo->vring[is_rx] != NULL && fifo->vring[is_rx] != vring)
+ return;
+
+ /* tx_reserve is used to reserved some room in FIFO for console. */
+ if (vring->vdev_id == VIRTIO_ID_NET) {
+ hdr_len = sizeof(struct virtio_net_hdr);
+ tx_reserve = fifo->tx_fifo_size / 16;
+ } else {
+ BUG_ON(vring->vdev_id != VIRTIO_ID_CONSOLE);
+ hdr_len = 0;
+ tx_reserve = 1;
+ }
+
+ desc = vring->desc;
+
+again:
+ while (1) {
+ /* Get available FIFO space. */
+ if (num_avail == 0) {
+ if (is_rx) {
+ /* Get the number of available words in FIFO. */
+ sts = readq(fifo->rx_base + TMFIFO_RX_STS);
+ num_avail = TMFIFO_RX_GET_STS_CNT(sts);
+
+ /* Don't continue if nothing in FIFO. */
+ if (num_avail <= 0)
+ break;
+ } else {
+ /* Get available space in FIFO. */
+ sts = readq(fifo->tx_base + TMFIFO_TX_STS);
+ num_avail = fifo->tx_fifo_size - tx_reserve -
+ TMFIFO_TX_GET_STS_CNT(sts);
+
+ if (num_avail <= 0)
+ break;
+ }
+ }
+
+ /* Console output always comes from the Tx buffer. */
+ if (!is_rx && vring->vdev_id == VIRTIO_ID_CONSOLE &&
+ cons != NULL && cons->tx_buf != NULL) {
+ for (;;) {
+ spin_lock_irqsave(&tmfifo_spin_lock, flags);
+ if (cons->tx_head == cons->tx_tail) {
+ spin_unlock_irqrestore(
+ &tmfifo_spin_lock, flags);
+ return;
+ }
+ addr = cons->tx_buf + cons->tx_head;
+ writeq(cpu_to_le64(*(u64 *)addr),
+ fifo->tx_base + TMFIFO_TX_DATA);
+ TMFIFO_VDEV_TX_BUF_POP(cons, sizeof(u64));
+ spin_unlock_irqrestore(&tmfifo_spin_lock,
+ flags);
+ if (--num_avail <= 0)
+ goto again;
+ }
+ }
+
+ /* Get the desc of next packet. */
+ if (!desc) {
+ /* Save the head desc of the chain. */
+ vring->desc_head = tmfifo_virtio_get_next_desc(vq);
+ if (!vring->desc_head) {
+ vring->desc = NULL;
+ return;
+ }
+ desc = vring->desc_head;
+ vring->desc = desc;
+
+ if (is_rx && vring->vdev_id == VIRTIO_ID_NET) {
+ struct virtio_net_hdr *net_hdr;
+
+ /* Initialize the packet header. */
+ net_hdr = (struct virtio_net_hdr *)
+ phys_to_virt(virtio64_to_cpu(
+ vdev, desc->addr));
+ memset(net_hdr, 0, sizeof(*net_hdr));
+ }
+ }
+
+ /* Beginning of each packet. */
+ if (vring->pkt_len == 0) {
+ int vdev_id, vring_change = 0;
+ union tmfifo_msg_hdr hdr;
+
+ num_avail--;
+
+ /* Read/Write packet length. */
+ if (is_rx) {
+ hdr.data = readq(fifo->rx_base +
+ TMFIFO_RX_DATA);
+ hdr.data = le64_to_cpu(hdr.data);
+
+ /* Skip the length 0 packet (keepalive). */
+ if (hdr.len == 0)
+ continue;
+
+ /* Check packet type. */
+ if (hdr.type == VIRTIO_ID_NET) {
+ vdev_id = VIRTIO_ID_NET;
+ hdr_len = sizeof(struct virtio_net_hdr);
+ } else if (hdr.type == VIRTIO_ID_CONSOLE) {
+ vdev_id = VIRTIO_ID_CONSOLE;
+ hdr_len = 0;
+ } else {
+ continue;
+ }
+
+ /*
+ * Check whether the new packet still belongs
+ * to this vring or not. If not, update the
+ * pkt_len of the new vring and return.
+ */
+ if (vdev_id != vring->vdev_id) {
+ struct tmfifo_vdev *dev2 =
+ fifo->vdev[vdev_id];
+
+ if (!dev2)
+ break;
+ vring->desc = desc;
+ vring = &dev2->vrings[TMFIFO_VRING_RX];
+ vring_change = 1;
+ }
+ vring->pkt_len = ntohs(hdr.len) + hdr_len;
+ } else {
+ vring->pkt_len = tmfifo_virtio_get_pkt_len(
+ vdev, desc, vr);
+
+ hdr.data = 0;
+ hdr.type = (vring->vdev_id == VIRTIO_ID_NET) ?
+ VIRTIO_ID_NET :
+ VIRTIO_ID_CONSOLE;
+ hdr.len = htons(vring->pkt_len - hdr_len);
+ writeq(cpu_to_le64(hdr.data),
+ fifo->tx_base + TMFIFO_TX_DATA);
+ }
+
+ vring->cur_len = hdr_len;
+ vring->rem_len = vring->pkt_len;
+ fifo->vring[is_rx] = vring;
+
+ if (vring_change)
+ return;
+ continue;
+ }
+
+ /* Check available space in this desc. */
+ len = virtio32_to_cpu(vdev, desc->len);
+ if (len > vring->rem_len)
+ len = vring->rem_len;
+
+ /* Check if the current desc is already done. */
+ if (vring->cur_len == len)
+ goto check_done;
+
+ addr = phys_to_virt(virtio64_to_cpu(vdev, desc->addr));
+
+ /* Read a word from FIFO for Rx. */
+ if (is_rx) {
+ data = readq(fifo->rx_base + TMFIFO_RX_DATA);
+ data = le64_to_cpu(data);
+ }
+
+ if (vring->cur_len + sizeof(u64) <= len) {
+ /* The whole word. */
+ if (is_rx) {
+ memcpy(addr + vring->cur_len, &data,
+ sizeof(u64));
+ } else {
+ memcpy(&data, addr + vring->cur_len,
+ sizeof(u64));
+ }
+ vring->cur_len += sizeof(u64);
+ } else {
+ /* Leftover bytes. */
+ BUG_ON(vring->cur_len > len);
+ if (is_rx) {
+ memcpy(addr + vring->cur_len, &data,
+ len - vring->cur_len);
+ } else {
+ memcpy(&data, addr + vring->cur_len,
+ len - vring->cur_len);
+ }
+ vring->cur_len = len;
+ }
+
+ /* Write the word into FIFO for Tx. */
+ if (!is_rx) {
+ writeq(cpu_to_le64(data),
+ fifo->tx_base + TMFIFO_TX_DATA);
+ }
+
+ num_avail--;
+
+check_done:
+ /* Check whether this desc is full or completed. */
+ if (vring->cur_len == len) {
+ vring->cur_len = 0;
+ vring->rem_len -= len;
+
+ /* Get the next desc on the chain. */
+ if (vring->rem_len > 0 &&
+ (virtio16_to_cpu(vdev, desc->flags) &
+ VRING_DESC_F_NEXT)) {
+ idx = virtio16_to_cpu(vdev, desc->next);
+ desc = &vr->desc[idx];
+ continue;
+ }
+
+ /* Done and release the desc. */
+ tmfifo_release_pkt(vdev, vring, &desc);
+ fifo->vring[is_rx] = NULL;
+
+ /* Notify upper layer that packet is done. */
+ spin_lock_irqsave(&tmfifo_spin_lock, flags);
+ vring_interrupt(0, vq);
+ spin_unlock_irqrestore(&tmfifo_spin_lock, flags);
+ continue;
+ }
+ }
+
+ /* Save the current desc. */
+ vring->desc = desc;
+}
+
+/* The notify function is called when new buffers are posted. */
+static bool tmfifo_virtio_notify(struct virtqueue *vq)
+{
+ struct tmfifo_vring *vring = (struct tmfifo_vring *)vq->priv;
+ struct tmfifo *fifo = vring->fifo;
+ unsigned long flags;
+
+ /*
+ * Virtio maintains vrings in pairs, even number ring for Rx
+ * and odd number ring for Tx.
+ */
+ if (!(vring->id & 1)) {
+ /* Set the RX HWM bit to start Rx. */
+ if (!test_and_set_bit(TM_RX_HWM_IRQ, &fifo->pend_events))
+ schedule_work(&fifo->work);
+ } else {
+ /*
+ * Console could make blocking call with interrupts disabled.
+ * In such case, the vring needs to be served right away. For
+ * other cases, just set the TX LWM bit to start Tx in the
+ * worker handler.
+ */
+ if (vring->vdev_id == VIRTIO_ID_CONSOLE) {
+ spin_lock_irqsave(&tmfifo_spin_lock, flags);
+ tmfifo_console_output(fifo->vdev[VIRTIO_ID_CONSOLE],
+ vq);
+ spin_unlock_irqrestore(&tmfifo_spin_lock, flags);
+ schedule_work(&fifo->work);
+ } else if (!test_and_set_bit(TM_TX_LWM_IRQ, &fifo->pend_events))
+ schedule_work(&fifo->work);
+ }
+
+ return true;
+}
+
+/* Get the array of feature bits for this device. */
+static u64 tmfifo_virtio_get_features(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ return tm_vdev->features;
+}
+
+/* Confirm device features to use. */
+static int tmfifo_virtio_finalize_features(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ tm_vdev->features = vdev->features;
+ return 0;
+}
+
+/* Free virtqueues found by find_vqs(). */
+static void tmfifo_virtio_del_vqs(struct virtio_device *vdev)
+{
+ int i;
+ struct tmfifo_vring *vring;
+ struct virtqueue *vq;
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+ vring = &tm_vdev->vrings[i];
+
+ /* Release the pending packet. */
+ if (vring->desc != NULL)
+ tmfifo_release_pkt(&tm_vdev->vdev, vring, &vring->desc);
+
+ vq = vring->vq;
+ if (vq) {
+ vring->vq = NULL;
+ vring_del_virtqueue(vq);
+ }
+ }
+}
+
+/* Create and initialize the virtual queues. */
+static int tmfifo_virtio_find_vqs(struct virtio_device *vdev,
+ unsigned int nvqs,
+ struct virtqueue *vqs[],
+ vq_callback_t *callbacks[],
+ const char * const names[],
+ const bool *ctx,
+ struct irq_affinity *desc)
+{
+ int i, ret = -EINVAL, size;
+ struct tmfifo_vring *vring;
+ struct virtqueue *vq;
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ if (nvqs > ARRAY_SIZE(tm_vdev->vrings))
+ return -EINVAL;
+
+ for (i = 0; i < nvqs; ++i) {
+ if (!names[i])
+ goto error;
+ vring = &tm_vdev->vrings[i];
+
+ /* zero vring */
+ size = vring_size(vring->size, vring->align);
+ memset(vring->va, 0, size);
+ vq = vring_new_virtqueue(i, vring->size, vring->align, vdev,
+ false, false, vring->va,
+ tmfifo_virtio_notify,
+ callbacks[i], names[i]);
+ if (!vq) {
+ dev_err(&vdev->dev, "vring_new_virtqueue failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ vqs[i] = vq;
+ vring->vq = vq;
+ vq->priv = vring;
+ }
+
+ return 0;
+
+error:
+ tmfifo_virtio_del_vqs(vdev);
+ return ret;
+}
+
+/* Read the status byte. */
+static u8 tmfifo_virtio_get_status(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ return tm_vdev->status;
+}
+
+/* Write the status byte. */
+static void tmfifo_virtio_set_status(struct virtio_device *vdev, u8 status)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ tm_vdev->status = status;
+}
+
+/* Reset the device. Not much here for now. */
+static void tmfifo_virtio_reset(struct virtio_device *vdev)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ tm_vdev->status = 0;
+}
+
+/* Read the value of a configuration field. */
+static void tmfifo_virtio_get(struct virtio_device *vdev,
+ unsigned int offset,
+ void *buf,
+ unsigned int len)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ if (offset + len > sizeof(tm_vdev->config) || offset + len < len) {
+ dev_err(vdev->dev.parent, "virtio_get access out of bounds\n");
+ return;
+ }
+
+ memcpy(buf, (u8 *)&tm_vdev->config + offset, len);
+}
+
+/* Write the value of a configuration field. */
+static void tmfifo_virtio_set(struct virtio_device *vdev,
+ unsigned int offset,
+ const void *buf,
+ unsigned int len)
+{
+ struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+ vdev);
+
+ if (offset + len > sizeof(tm_vdev->config) || offset + len < len) {
+ dev_err(vdev->dev.parent, "virtio_get access out of bounds\n");
+ return;
+ }
+
+ memcpy((u8 *)&tm_vdev->config + offset, buf, len);
+}
+
+/* Virtio config operations. */
+static const struct virtio_config_ops tmfifo_virtio_config_ops = {
+ .get_features = tmfifo_virtio_get_features,
+ .finalize_features = tmfifo_virtio_finalize_features,
+ .find_vqs = tmfifo_virtio_find_vqs,
+ .del_vqs = tmfifo_virtio_del_vqs,
+ .reset = tmfifo_virtio_reset,
+ .set_status = tmfifo_virtio_set_status,
+ .get_status = tmfifo_virtio_get_status,
+ .get = tmfifo_virtio_get,
+ .set = tmfifo_virtio_set,
+};
+
+/* Create vdev type in a tmfifo. */
+int tmfifo_create_vdev(struct tmfifo *fifo, int vdev_id, u64 features,
+ void *config, u32 size)
+{
+ struct tmfifo_vdev *tm_vdev;
+ int ret = 0;
+
+ mutex_lock(&fifo->lock);
+
+ tm_vdev = fifo->vdev[vdev_id];
+ if (tm_vdev != NULL) {
+ pr_err("vdev %d already exists\n", vdev_id);
+ ret = -EEXIST;
+ goto already_exist;
+ }
+
+ tm_vdev = kzalloc(sizeof(*tm_vdev), GFP_KERNEL);
+ if (!tm_vdev) {
+ ret = -ENOMEM;
+ goto already_exist;
+ }
+
+ tm_vdev->vdev.id.device = vdev_id;
+ tm_vdev->vdev.config = &tmfifo_virtio_config_ops;
+ tm_vdev->vdev.dev.parent = &fifo->pdev->dev;
+ tm_vdev->vdev.dev.release = tmfifo_virtio_dev_release;
+ tm_vdev->features = features;
+ if (config)
+ memcpy(&tm_vdev->config, config, size);
+ if (tmfifo_alloc_vrings(fifo, tm_vdev, vdev_id)) {
+ pr_err("Unable to allocate vring\n");
+ ret = -ENOMEM;
+ goto alloc_vring_fail;
+ }
+ if (vdev_id == VIRTIO_ID_CONSOLE) {
+ tm_vdev->tx_buf = kmalloc(TMFIFO_CONS_TX_BUF_SIZE,
+ GFP_KERNEL);
+ }
+ fifo->vdev[vdev_id] = tm_vdev;
+
+ /* Register the virtio device. */
+ ret = register_virtio_device(&tm_vdev->vdev);
+ if (ret) {
+ dev_err(&fifo->pdev->dev, "register_virtio_device() failed\n");
+ goto register_fail;
+ }
+
+ mutex_unlock(&fifo->lock);
+ return 0;
+
+register_fail:
+ tmfifo_free_vrings(fifo, vdev_id);
+ fifo->vdev[vdev_id] = NULL;
+alloc_vring_fail:
+ kfree(tm_vdev);
+already_exist:
+ mutex_unlock(&fifo->lock);
+ return ret;
+}
+
+/* Delete vdev type from a tmfifo. */
+int tmfifo_delete_vdev(struct tmfifo *fifo, int vdev_id)
+{
+ struct tmfifo_vdev *tm_vdev;
+
+ mutex_lock(&fifo->lock);
+
+ /* Unregister vdev. */
+ tm_vdev = fifo->vdev[vdev_id];
+ if (tm_vdev) {
+ unregister_virtio_device(&tm_vdev->vdev);
+ tmfifo_free_vrings(fifo, vdev_id);
+ kfree(tm_vdev->tx_buf);
+ kfree(tm_vdev);
+ fifo->vdev[vdev_id] = NULL;
+ }
+
+ mutex_unlock(&fifo->lock);
+
+ return 0;
+}
+
+/* Device remove function. */
+static int tmfifo_remove(struct platform_device *pdev)
+{
+ int i;
+ struct tmfifo *fifo = platform_get_drvdata(pdev);
+ struct resource *rx_res, *tx_res;
+
+ tmfifo_ready = false;
+
+ if (fifo) {
+ mutex_lock(&tmfifo_lock);
+
+ /* Stop the timer. */
+ del_timer_sync(&fifo->timer);
+
+ /* Release interrupts. */
+ tmfifo_free_irqs(fifo);
+
+ /* Cancel the pending work. */
+ cancel_work_sync(&fifo->work);
+
+ for (i = 0; i < TMFIFO_VDEV_MAX; i++)
+ tmfifo_delete_vdev(fifo, i);
+
+ /* Release IO resources. */
+ if (fifo->rx_base)
+ iounmap(fifo->rx_base);
+ if (fifo->tx_base)
+ iounmap(fifo->tx_base);
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(fifo);
+
+ mutex_unlock(&tmfifo_lock);
+ }
+
+ rx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (rx_res)
+ release_mem_region(rx_res->start, resource_size(rx_res));
+ tx_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (tx_res)
+ release_mem_region(tx_res->start, resource_size(tx_res));
+
+ return 0;
+}
+
+/* Read the configured network MAC address from efi variable. */
+static void tmfifo_get_cfg_mac(u8 *mac)
+{
+ u8 buf[6];
+ efi_status_t status;
+ unsigned long size = sizeof(buf);
+ efi_char16_t name[] = { 'R', 's', 'h', 'i', 'm', 'M', 'a', 'c',
+ 'A', 'd', 'd', 'r', 0 };
+ efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID;
+
+ status = efi.get_variable(name, &guid, NULL, &size, buf);
+ if (status == EFI_SUCCESS && size == sizeof(buf))
+ memcpy(mac, buf, sizeof(buf));
+}
+
+/* Probe the TMFIFO. */
+static int tmfifo_probe(struct platform_device *pdev)
+{
+ u64 ctl;
+ struct tmfifo *fifo;
+ struct resource *rx_res, *tx_res;
+ struct virtio_net_config net_config;
+ int i, ret;
+
+ /* Get the resource of the Rx & Tx FIFO. */
+ rx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ tx_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!rx_res || !tx_res) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (request_mem_region(rx_res->start,
+ resource_size(rx_res), "bf-tmfifo") == NULL) {
+ ret = -EBUSY;
+ goto early_err;
+ }
+
+ if (request_mem_region(tx_res->start,
+ resource_size(tx_res), "bf-tmfifo") == NULL) {
+ release_mem_region(rx_res->start, resource_size(rx_res));
+ ret = -EBUSY;
+ goto early_err;
+ }
+
+ ret = -ENOMEM;
+ fifo = kzalloc(sizeof(struct tmfifo), GFP_KERNEL);
+ if (!fifo)
+ goto err;
+
+ fifo->pdev = pdev;
+ platform_set_drvdata(pdev, fifo);
+
+ INIT_WORK(&fifo->work, tmfifo_work_handler);
+
+ timer_setup(&fifo->timer, tmfifo_timer, 0);
+ fifo->timer.function = tmfifo_timer;
+
+ for (i = 0; i < TM_IRQ_CNT; i++) {
+ fifo->irq[i] = platform_get_irq(pdev, i);
+ ret = request_irq(fifo->irq[i], tmfifo_irq_handler, 0,
+ "tmfifo", (u8 *)fifo + i);
+ if (ret) {
+ pr_err("Unable to request irq\n");
+ fifo->irq[i] = 0;
+ goto err;
+ }
+ }
+
+ fifo->rx_base = ioremap(rx_res->start, resource_size(rx_res));
+ if (!fifo->rx_base)
+ goto err;
+
+ fifo->tx_base = ioremap(tx_res->start, resource_size(tx_res));
+ if (!fifo->tx_base)
+ goto err;
+
+ /* Get Tx FIFO size and set the low/high watermark. */
+ ctl = readq(fifo->tx_base + TMFIFO_TX_CTL);
+ fifo->tx_fifo_size =
+ TMFIFO_GET_FIELD(ctl, TMFIFO_TX_CTL__MAX_ENTRIES);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_TX_CTL__LWM, fifo->tx_fifo_size / 2);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_TX_CTL__HWM, fifo->tx_fifo_size - 1);
+ writeq(ctl, fifo->tx_base + TMFIFO_TX_CTL);
+
+ /* Get Rx FIFO size and set the low/high watermark. */
+ ctl = readq(fifo->rx_base + TMFIFO_RX_CTL);
+ fifo->rx_fifo_size =
+ TMFIFO_GET_FIELD(ctl, TMFIFO_RX_CTL__MAX_ENTRIES);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_RX_CTL__LWM, 0);
+ ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_RX_CTL__HWM, 1);
+ writeq(ctl, fifo->rx_base + TMFIFO_RX_CTL);
+
+ mutex_init(&fifo->lock);
+
+ /* Create the console vdev. */
+ ret = tmfifo_create_vdev(fifo, VIRTIO_ID_CONSOLE, 0, NULL, 0);
+ if (ret)
+ goto err;
+
+ /* Create the network vdev. */
+ memset(&net_config, 0, sizeof(net_config));
+ net_config.mtu = TMFIFO_NET_MTU;
+ net_config.status = VIRTIO_NET_S_LINK_UP;
+ memcpy(net_config.mac, tmfifo_net_default_mac, 6);
+ tmfifo_get_cfg_mac(net_config.mac);
+ ret = tmfifo_create_vdev(fifo, VIRTIO_ID_NET, TMFIFO_NET_FEATURES,
+ &net_config, sizeof(net_config));
+ if (ret)
+ goto err;
+
+ mod_timer(&fifo->timer, jiffies + tmfifo_timer_interval);
+
+ tmfifo_ready = true;
+
+ return 0;
+
+err:
+ tmfifo_remove(pdev);
+early_err:
+ dev_err(&pdev->dev, "Probe Failed\n");
+ return ret;
+}
+
+static const struct of_device_id tmfifo_match[] = {
+ { .compatible = "mellanox,bf-tmfifo" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tmfifo_match);
+
+static const struct acpi_device_id bf_tmfifo_acpi_match[] = {
+ { "MLNXBF01", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, bf_tmfifo_acpi_match);
+
+static struct platform_driver tmfifo_driver = {
+ .probe = tmfifo_probe,
+ .remove = tmfifo_remove,
+ .driver = {
+ .name = "bf-tmfifo",
+ .of_match_table = tmfifo_match,
+ .acpi_match_table = ACPI_PTR(bf_tmfifo_acpi_match),
+ },
+};
+
+static int __init tmfifo_init(void)
+{
+ int ret;
+
+ mutex_init(&tmfifo_lock);
+
+ ret = platform_driver_register(&tmfifo_driver);
+ if (ret)
+ pr_err("Failed to register tmfifo driver.\n");
+
+ return ret;
+}
+
+static void __exit tmfifo_exit(void)
+{
+ platform_driver_unregister(&tmfifo_driver);
+}
+
+module_init(tmfifo_init);
+module_exit(tmfifo_exit);
+
+MODULE_DESCRIPTION("Mellanox BlueField SoC TMFIFO Driver");
+MODULE_AUTHOR("Mellanox Technologies, Ltd");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.7");
diff --git a/drivers/soc/mellanox/tmfifo_regs.h b/drivers/soc/mellanox/tmfifo_regs.h
new file mode 100644
index 0000000..b07f353
--- /dev/null
+++ b/drivers/soc/mellanox/tmfifo_regs.h
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __TMFIFO_REGS_H__
+#define __TMFIFO_REGS_H__
+
+#ifdef __ASSEMBLER__
+#define _64bit(x) x
+#else /* __ASSEMBLER__ */
+#ifdef __tile__
+#define _64bit(x) x ## UL
+#else /* __tile__ */
+#define _64bit(x) x ## ULL
+#endif /* __tile__ */
+#endif /* __ASSEMBLER */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
+#ifndef __DOXYGEN__
+
+#define TMFIFO_TX_DATA 0x0
+
+#define TMFIFO_TX_STS 0x8
+#define TMFIFO_TX_STS__LENGTH 0x0001
+#define TMFIFO_TX_STS__COUNT_SHIFT 0
+#define TMFIFO_TX_STS__COUNT_WIDTH 9
+#define TMFIFO_TX_STS__COUNT_RESET_VAL 0
+#define TMFIFO_TX_STS__COUNT_RMASK 0x1ff
+#define TMFIFO_TX_STS__COUNT_MASK 0x1ff
+
+#define TMFIFO_TX_CTL 0x10
+#define TMFIFO_TX_CTL__LENGTH 0x0001
+#define TMFIFO_TX_CTL__LWM_SHIFT 0
+#define TMFIFO_TX_CTL__LWM_WIDTH 8
+#define TMFIFO_TX_CTL__LWM_RESET_VAL 128
+#define TMFIFO_TX_CTL__LWM_RMASK 0xff
+#define TMFIFO_TX_CTL__LWM_MASK 0xff
+#define TMFIFO_TX_CTL__HWM_SHIFT 8
+#define TMFIFO_TX_CTL__HWM_WIDTH 8
+#define TMFIFO_TX_CTL__HWM_RESET_VAL 128
+#define TMFIFO_TX_CTL__HWM_RMASK 0xff
+#define TMFIFO_TX_CTL__HWM_MASK 0xff00
+#define TMFIFO_TX_CTL__MAX_ENTRIES_SHIFT 32
+#define TMFIFO_TX_CTL__MAX_ENTRIES_WIDTH 9
+#define TMFIFO_TX_CTL__MAX_ENTRIES_RESET_VAL 256
+#define TMFIFO_TX_CTL__MAX_ENTRIES_RMASK 0x1ff
+#define TMFIFO_TX_CTL__MAX_ENTRIES_MASK _64bit(0x1ff00000000)
+
+#define TMFIFO_RX_DATA 0x0
+
+#define TMFIFO_RX_STS 0x8
+#define TMFIFO_RX_STS__LENGTH 0x0001
+#define TMFIFO_RX_STS__COUNT_SHIFT 0
+#define TMFIFO_RX_STS__COUNT_WIDTH 9
+#define TMFIFO_RX_STS__COUNT_RESET_VAL 0
+#define TMFIFO_RX_STS__COUNT_RMASK 0x1ff
+#define TMFIFO_RX_STS__COUNT_MASK 0x1ff
+
+#define TMFIFO_RX_CTL 0x10
+#define TMFIFO_RX_CTL__LENGTH 0x0001
+#define TMFIFO_RX_CTL__LWM_SHIFT 0
+#define TMFIFO_RX_CTL__LWM_WIDTH 8
+#define TMFIFO_RX_CTL__LWM_RESET_VAL 128
+#define TMFIFO_RX_CTL__LWM_RMASK 0xff
+#define TMFIFO_RX_CTL__LWM_MASK 0xff
+#define TMFIFO_RX_CTL__HWM_SHIFT 8
+#define TMFIFO_RX_CTL__HWM_WIDTH 8
+#define TMFIFO_RX_CTL__HWM_RESET_VAL 128
+#define TMFIFO_RX_CTL__HWM_RMASK 0xff
+#define TMFIFO_RX_CTL__HWM_MASK 0xff00
+#define TMFIFO_RX_CTL__MAX_ENTRIES_SHIFT 32
+#define TMFIFO_RX_CTL__MAX_ENTRIES_WIDTH 9
+#define TMFIFO_RX_CTL__MAX_ENTRIES_RESET_VAL 256
+#define TMFIFO_RX_CTL__MAX_ENTRIES_RMASK 0x1ff
+#define TMFIFO_RX_CTL__MAX_ENTRIES_MASK _64bit(0x1ff00000000)
+
+#endif /* !defined(__DOXYGEN__) */
+#endif /* !defined(__TMFIFO_REGS_H__) */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v1 2/4] arm64: Add Mellanox BlueField SoC config option
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b143b40446c1870fb8d422b364ead95d54552be9.1527264077.git.lsun@mellanox.com>
This commit introduces config option for Mellanox BlueField SoC,
which can be used to build the SoC specific drivers, and enables
it by default in configs/defconfig.
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
arch/arm64/Kconfig.platforms | 6 ++++++
arch/arm64/configs/defconfig | 1 +
2 files changed, 7 insertions(+)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2b1535c..74ad03f 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -110,6 +110,12 @@ config ARCH_MESON
help
This enables support for the Amlogic S905 SoCs.
+config ARCH_MLNX_BLUEFIELD
+ bool "Mellanox BlueField SoC Family"
+ select SOC_MLNX
+ help
+ This enables support for the Mellanox BlueField SoC.
+
config ARCH_MVEBU
bool "Marvell EBU SoC Family"
select ARMADA_AP806_SYSCON
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1c98939..842f607 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -43,6 +43,7 @@ CONFIG_ARCH_LG1K=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_MEDIATEK=y
CONFIG_ARCH_MESON=y
+CONFIG_ARCH_MLNX_BLUEFIELD=y
CONFIG_ARCH_MVEBU=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_ROCKCHIP=y
--
1.8.3.1
^ permalink raw reply related
* [PATCH v1 3/4] dt-bindings: soc: Add TmFifo binding for Mellanox BlueField SoC
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b143b40446c1870fb8d422b364ead95d54552be9.1527264077.git.lsun@mellanox.com>
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
.../devicetree/bindings/soc/mellanox/tmfifo.txt | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
diff --git a/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt b/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
new file mode 100644
index 0000000..0a362f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
@@ -0,0 +1,20 @@
+* Mellanox BlueField SoC TmFifo
+
+BlueField TmFifo provides a shared FIFO between the target and the
+external host machine, which can be accessed via USB or PCIe.
+
+Required properties:
+
+- compatible: Should be "mellanox,bf-tmfifo"
+- reg: Physical base address and length of Rx/Tx block
+- interrupts: The interrupt number of Rx low water mark, Rx high water mark
+ Tx low water mark, Tx high water mark respectively.
+
+Example:
+
+tmfifo at 800a20 {
+ compatible = "mellanox,bf-tmfifo";
+ reg = <0x00800a20 0x00000018
+ 0x00800a40 0x00000018>;
+ interrupts = <41, 42, 43, 44>;
+};
--
1.8.3.1
^ permalink raw reply related
* [PATCH v1 4/4] MAINTAINERS: Add entry for Mellanox Bluefield Soc
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b143b40446c1870fb8d422b364ead95d54552be9.1527264077.git.lsun@mellanox.com>
Add maintainer information for Mellanox BlueField SoC.
Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 58b9861..85d5639 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1636,6 +1636,14 @@ L: linux-mediatek at lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/phy/mediatek/phy-mtk-tphy.c
+ARM/Mellanox BlueField SoC support
+M: David Woods <dwoods@mellanox.com>
+M: Liming Sun <lsun@mellanox.com>
+L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/soc/mellanox/*
+F: Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
+
ARM/MICREL KS8695 ARCHITECTURE
M: Greg Ungerer <gerg@uclinux.org>
L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
--
1.8.3.1
^ permalink raw reply related
* [PATCH 08/11] coresight: Add generic TMC sg table framework
From: Suzuki K Poulose @ 2018-05-25 16:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180523202552.GA4609@xps15>
On 23/05/18 21:25, Mathieu Poirier wrote:
> On Fri, May 18, 2018 at 05:39:24PM +0100, Suzuki K Poulose wrote:
>> This patch introduces a generic sg table data structure and
>> associated operations. An SG table can be used to map a set
>> of Data pages where the trace data could be stored by the TMC
>> ETR. The information about the data pages could be stored in
>> different formats, depending on the type of the underlying
>> SG mechanism (e.g, TMC ETR SG vs Coresight CATU). The generic
>> structure provides book keeping of the pages used for the data
>> as well as the table contents. The table should be filled by
>> the user of the infrastructure.
>>
>> A table can be created by specifying the number of data pages
>> as well as the number of table pages required to hold the
>> pointers, where the latter could be different for different
>> types of tables. The pages are mapped in the appropriate dma
>> data direction mode (i.e, DMA_TO_DEVICE for table pages
>> and DMA_FROM_DEVICE for data pages). The framework can optionally
>> accept a set of allocated data pages (e.g, perf ring buffer) and
>> map them accordingly. The table and data pages are vmap'ed to allow
>> easier access by the drivers. The framework also provides helpers to
>> sync the data written to the pages with appropriate directions.
>>
>> This will be later used by the TMC ETR SG unit and CATU.
>>
>> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>> Changes since v1:
>> - Address code style issues, more comments
>> ---
>> drivers/hwtracing/coresight/coresight-tmc-etr.c | 290 ++++++++++++++++++++++++
>> drivers/hwtracing/coresight/coresight-tmc.h | 50 ++++
>> 2 files changed, 340 insertions(+)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index 9780798..1e844f8 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -17,9 +17,299 @@
>> +static inline dma_addr_t tmc_sg_table_base_paddr(struct tmc_sg_table *sg_table)
>> +{
>> + if (WARN_ON(!sg_table->data_pages.pages[0]))
>> + return 0;
>> + return sg_table->table_daddr;
>> +}
>> +
>> +static inline void *tmc_sg_table_base_vaddr(struct tmc_sg_table *sg_table)
>> +{
>> + if (WARN_ON(!sg_table->data_pages.pages[0]))
>> + return NULL;
>> + return sg_table->table_vaddr;
>> +}
>
> The above two functions deal with DMA'able and virtual addresses for the table
> page buffer. Yet the test in the WARN_ON is done on the data page array.
> Shouldn't this be sg_table->table_pages.pages[0] instead?
The table is as good as empty if there are no data pages associated with
the table. Hence the data_pages check.
>
> If not please add a comment justifying your position so that someone else
> looking at the code does't end up thinking the same in a year from now.
I will add a comment to reflect the above.
>
>> +
>> +static inline void *
>> +tmc_sg_table_data_vaddr(struct tmc_sg_table *sg_table)
>> +{
>> + if (WARN_ON(!sg_table->data_pages.nr_pages))
>> + return 0;
>> + return sg_table->data_vaddr;
>> +}
>
> I see that tmc_sg_table_base_vaddr() and tmc_sg_table_data_vaddr() are both
> returning the virtual address of the contiguous buffer for table and data
> respectively. Yet there is a discrepency in the naming convention. I would
> have expected tmc_sg_table_base_vaddr() and tmc_sg_data_base_vaddr() so that
> there is a little symmetry between them.
Agree. I will fix it.
Suzuki
^ permalink raw reply
* [PATCH] usb/gadget: aspeed-vhub: add USB_LIBCOMPOSITE dependency
From: Arnd Bergmann @ 2018-05-25 16:07 UTC (permalink / raw)
To: linux-arm-kernel
Without that option, we run into a link failure:
drivers/usb/gadget/udc/aspeed-vhub/hub.o: In function `ast_vhub_std_hub_request':
hub.c:(.text+0x5b0): undefined reference to `usb_gadget_get_string'
Fixes: 7ecca2a4080c ("usb/gadget: Add driver for Aspeed SoC virtual hub")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/usb/gadget/udc/aspeed-vhub/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/Kconfig b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
index f0cdf89b8503..83ba8a2eb6af 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
+++ b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
@@ -2,6 +2,7 @@
config USB_ASPEED_VHUB
tristate "Aspeed vHub UDC driver"
depends on ARCH_ASPEED || COMPILE_TEST
+ depends on USB_LIBCOMPOSITE
help
USB peripheral controller for the Aspeed AST2500 family
SoCs supporting the "vHub" functionality and USB2.0
--
2.9.0
^ permalink raw reply related
* [PATCH] arm64: vgic-v2: Fix proxying of cpuif access
From: Andrew Jones @ 2018-05-25 16:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180429140507.60bfe2dc@why.wild-wind.fr.eu.org>
On Sun, Apr 29, 2018 at 02:05:07PM +0100, Marc Zyngier wrote:
> On Sun, 29 Apr 2018 14:34:32 +0200
> Christoffer Dall <christoffer.dall@arm.com> wrote:
>
> > On Fri, Apr 27, 2018 at 03:51:02PM +0100, Marc Zyngier wrote:
> > > Proxying the cpuif accesses at EL2 makes use of vcpu_data_guest_to_host
> > > and co, which check the endianness, which call into vcpu_read_sys_reg...
> > > which isn't mapped at EL2 (it was inlined before, and got moved OoL
> > > with the VHE optimizations).
> >
> > I thought we relied on static inline functions to always be inlined, but
> > apparently not? Does this mean we have potential other bugs looming
> > depending on the mood of the compiler, or was there something special
> > that went wrong here?
>
> We do rely on that behaviour. And that was the case until you moved
> vcpu_read_sys_reg() to be entirely out of line (see d47533dab9f5).
>
> At that point, kvm_vcpu_is_be() becomes a death trap.
>
> We missed it for two reasons:
> - It was only indirectly called, making it quite hard to notice the
> potential breakage
> - Nobody gives a damn about 64k pages, specially on something like Juno
>
> What we'd need is a way to find cross-section calls (text -> hyp-text
> should allowed, but not the reverse). We already have similar things in
> the kernel, it is probably only a matter of reusing the infrastructure
> for our own purpose.
>
Hi all,
While debugging a series backported to the RHEL kernel, I was suspicious
of the problem being an issue like this (a hyp-text to non-hyp-mapped
reference), so I went ahead an implemented the cross-section reference
checking as Marc suggested. I've attached the patch. I don't really
like it though because of all the special casing necessary to kill
false alarms - making it too hacky. Also, the need to inline some
functions just to match their symbol names is pretty lame. Anyway,
maybe it can be helpful, at least as inspiration.
Running it on latest master doesn't produce anything. Running it
without b220244d4179 ("arm64: vgic-v2: Fix proxying of cpuif access")
gives
.hyp.text:__vgic_v2_perform_cpuif_access references .text:vcpu_read_sys_reg
so I guess it works.
Unfortunately it didn't help me with my downstream debug...
drew
-------------- next part --------------
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index bffece27b5c1..7a6364e8312f 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -200,6 +200,7 @@ ENDPROC(\label)
invalid_vector el2h_fiq_invalid
invalid_vector el1_fiq_invalid
+hyp_entry_literal_pool:
.ltorg
.align 11
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index d9645236e474..16f063af3bd9 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -86,7 +86,7 @@ static void __hyp_text __deactivate_traps_common(void)
write_sysreg(0, pmuserenr_el0);
}
-static void activate_traps_vhe(struct kvm_vcpu *vcpu)
+static noinline void activate_traps_vhe(struct kvm_vcpu *vcpu)
{
u64 val;
@@ -125,7 +125,7 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
__activate_traps_nvhe(vcpu);
}
-static void deactivate_traps_vhe(void)
+static noinline void deactivate_traps_vhe(void)
{
extern char vectors[]; /* kernel exception vectors */
write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
@@ -529,8 +529,8 @@ static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par,
read_sysreg(hpfar_el2), par, vcpu);
}
-static void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par,
- struct kvm_cpu_context *host_ctxt)
+static noinline void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par,
+ struct kvm_cpu_context *host_ctxt)
{
struct kvm_vcpu *vcpu;
vcpu = host_ctxt->__hyp_running_vcpu;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 4ff08a0ef5d3..6ba0617df985 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -964,6 +964,7 @@ enum mismatch {
ANY_EXIT_TO_ANY_INIT,
EXPORT_TO_INIT_EXIT,
EXTABLE_TO_NON_TEXT,
+ HYP_TEXT_TO_NON_HYP,
};
/**
@@ -1003,6 +1004,11 @@ static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
Elf_Rela *r, Elf_Sym *sym,
const char *fromsec);
+static void hyp_mismatch_handler(const char *modname, struct elf_info *elf,
+ const struct sectioncheck* const mismatch,
+ Elf_Rela *r, Elf_Sym *sym,
+ const char *fromsec);
+
static const struct sectioncheck sectioncheck[] = {
/* Do not reference init/exit code/data from
* normal code and data
@@ -1090,7 +1096,15 @@ static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
.good_tosec = {ALL_TEXT_SECTIONS , NULL},
.mismatch = EXTABLE_TO_NON_TEXT,
.handler = extable_mismatch_handler,
-}
+},
+{
+ .fromsec = { ".hyp.text", NULL },
+ .good_tosec = { ".hyp.text", ".hyp.idmap.text",
+ ".rodata", ".data..ro_after_init",
+ ".bss", NULL },
+ .mismatch = HYP_TEXT_TO_NON_HYP,
+ .handler = hyp_mismatch_handler,
+},
};
static const struct sectioncheck *section_mismatch(
@@ -1525,6 +1539,10 @@ static void report_sec_mismatch(const char *modname,
fatal("There's a special handler for this mismatch type, "
"we should never get here.");
break;
+ case HYP_TEXT_TO_NON_HYP:
+ fatal("There's a special handler for this mismatch type, "
+ "we should never get here.");
+ break;
}
fprintf(stderr, "\n");
}
@@ -1681,6 +1699,46 @@ static void extable_mismatch_handler(const char* modname, struct elf_info *elf,
}
}
+static void hyp_mismatch_handler(const char *modname, struct elf_info *elf,
+ const struct sectioncheck* const mismatch,
+ Elf_Rela *r, Elf_Sym *sym,
+ const char *fromsec)
+{
+ Elf_Sym *from = find_elf_symbol2(elf, r->r_offset, fromsec);
+ Elf_Sym *to = find_elf_symbol(elf, r->r_addend, sym);
+ const char *fromsym = sym_name(elf, from);
+ const char *tosec = sec_name(elf, get_secindex(elf, sym));
+ const char *tosym = sym_name(elf, to);
+ char *s;
+
+ switch (mismatch->mismatch) {
+ case HYP_TEXT_TO_NON_HYP:
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ if (!is_valid_name(elf, from) || !is_valid_name(elf, to)) {
+ /*
+ * Skip unknown symbols to reduce false alarms,
+ * of course at the risk of missing something...
+ */
+ return;
+ }
+ if (strcmp(tosym, "kvm_arm_hyp_stack_page") == 0 ||
+ strcmp(tosym, "kvm_host_cpu_state") == 0)
+ return;
+ if (strcmp(fromsym, "hyp_entry_literal_pool") == 0)
+ return;
+ if ((s = strstr(tosym, "_vhe")) &&
+ (strlen(s) == 4 || s[4] == '.'))
+ return;
+ fprintf(stderr,
+ ".hyp.text:%s references %s:%s\n\n",
+ fromsym, tosec, tosym);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
static void check_section_mismatch(const char *modname, struct elf_info *elf,
Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
{
^ permalink raw reply related
* [PATCH 1/2] ARM: stm32: Don't select DMA unconditionally on STM32MP157C
From: Arnd Bergmann @ 2018-05-25 16:09 UTC (permalink / raw)
To: linux-arm-kernel
The patch that enabled these had no useful changelog that explains
why it is done, and it causes a build warning:
WARNING: unmet direct dependencies detected for STM32_DMA
Depends on [n]: DMADEVICES [=n] && (ARCH_STM32 [=y] || COMPILE_TEST [=y])
Selected by [y]:
- MACH_STM32MP157 [=y] && ARCH_STM32 [=y] && ARCH_MULTI_V7 [=y]
Generally, platforms should not select arbitrary drivers, so let's
just revert that change.
Fixes: de6037fa207f ("ARM: stm32: Select DMA, DMAMUX and MDMA support on STM32MP157C")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mach-stm32/Kconfig | 3 ---
1 file changed, 3 deletions(-)
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index 82a93b8d9ae6..713c068b953f 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -46,9 +46,6 @@ if ARCH_MULTI_V7
config MACH_STM32MP157
bool "STMicroelectronics STM32MP157"
- select STM32_DMA
- select STM32_DMAMUX
- select STM32_MDMA
default y
endif # ARMv7-A
--
2.9.0
^ permalink raw reply related
* [PATCH 1/2] ARM: stm32: Don't select DMA unconditionally on STM32MP157C
From: Arnd Bergmann @ 2018-05-25 16:10 UTC (permalink / raw)
To: linux-arm-kernel
The patch that enabled these had no useful changelog that explains
why it is done, and it causes a build warning:
WARNING: unmet direct dependencies detected for STM32_DMA
Depends on [n]: DMADEVICES [=n] && (ARCH_STM32 [=y] || COMPILE_TEST [=y])
Selected by [y]:
- MACH_STM32MP157 [=y] && ARCH_STM32 [=y] && ARCH_MULTI_V7 [=y]
Generally, platforms should not select arbitrary drivers, so let's
just revert that change.
Fixes: de6037fa207f ("ARM: stm32: Select DMA, DMAMUX and MDMA support on STM32MP157C")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mach-stm32/Kconfig | 3 ---
1 file changed, 3 deletions(-)
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index 82a93b8d9ae6..713c068b953f 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -46,9 +46,6 @@ if ARCH_MULTI_V7
config MACH_STM32MP157
bool "STMicroelectronics STM32MP157"
- select STM32_DMA
- select STM32_DMAMUX
- select STM32_MDMA
default y
endif # ARMv7-A
--
2.9.0
^ permalink raw reply related
* [PATCH 2/2] ARM: shmobile: only call secure_cntvoff_init on SMP builds
From: Arnd Bergmann @ 2018-05-25 16:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525161051.187324-1-arnd@arndb.de>
The secure_cntvoff_init() function is not available without CONFIG_SMP,
leading to a link error on shmobile:
arch/arm/mach-shmobile/setup-rcar-gen2.o: In function `rcar_gen2_timer_init':
setup-rcar-gen2.c:(.init.text+0x18): undefined reference to `secure_cntvoff_init'
>From the description in commit 3fd45a136ff6 ("ARM: shmobile: rcar-gen2:
Make sure CNTVOFF is initialized on CA7/15"), I understand that we
don't need to call it on non-SMP builds because the boot CPU is always
initialized by common code, so we can simply avoid the reference by
checking for CONFIG_SMP.
Fixes: cad160ed0a94 ("ARM: shmobile: Convert file to use cntvoff")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm/mach-shmobile/setup-rcar-gen2.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index 88fdc1801d90..39085d7a8f37 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -71,7 +71,8 @@ void __init rcar_gen2_timer_init(void)
void __iomem *base;
u32 freq;
- secure_cntvoff_init();
+ if (IS_ENABLED(CONFIG_SMP))
+ secure_cntvoff_init();
if (of_machine_is_compatible("renesas,r8a7745") ||
of_machine_is_compatible("renesas,r8a77470") ||
--
2.9.0
^ permalink raw reply related
* [PATCH v3 7/8] drm/mediatek: Add support for mediatek SOC MT2712
From: kbuild test robot @ 2018-05-25 16:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527215665-11937-8-git-send-email-stu.hsieh@mediatek.com>
Hi Stu,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.17-rc6 next-20180517]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/stu-hsieh-mediatek-com/Add-support-for-mediatek-SOC-MT2712/20180525-211114
base: git://people.freedesktop.org/~airlied/linux.git drm-next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All error/warnings (new ones prefixed by >>):
>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:165:2: error: 'DDP_COMPONENT_DPI1' undeclared here (not in a function); did you mean 'DDP_COMPONENT_DSI1'?
DDP_COMPONENT_DPI1,
^~~~~~~~~~~~~~~~~~
DDP_COMPONENT_DSI1
>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:171:2: error: 'DDP_COMPONENT_DSI2' undeclared here (not in a function); did you mean 'DDP_COMPONENT_DSI1'?
DDP_COMPONENT_DSI2,
^~~~~~~~~~~~~~~~~~
DDP_COMPONENT_DSI1
>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:171:2: error: incompatible types when initializing type 'enum mtk_ddp_comp_id' using type 'const enum mtk_ddp_comp_id *'
>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:207:16: warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
.third_path = mt2712_mtk_ddp_third,
^~~~~~~~~~~~~~~~~~~~
vim +165 drivers/gpu//drm/mediatek/mtk_drm_drv.c
158
159 static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = {
160 DDP_COMPONENT_OVL1,
161 DDP_COMPONENT_COLOR1,
162 DDP_COMPONENT_AAL1,
163 DDP_COMPONENT_OD1,
164 DDP_COMPONENT_RDMA1,
> 165 DDP_COMPONENT_DPI1,
166 DDP_COMPONENT_PWM1,
167 };
168
169 static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third[] = {
170 DDP_COMPONENT_RDMA2,
> 171 DDP_COMPONENT_DSI2,
172 DDP_COMPONENT_PWM2,
173 };
174
175 static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
176 DDP_COMPONENT_OVL0,
177 DDP_COMPONENT_COLOR0,
178 DDP_COMPONENT_AAL0,
179 DDP_COMPONENT_OD0,
180 DDP_COMPONENT_RDMA0,
181 DDP_COMPONENT_UFOE,
182 DDP_COMPONENT_DSI0,
183 DDP_COMPONENT_PWM0,
184 };
185
186 static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
187 DDP_COMPONENT_OVL1,
188 DDP_COMPONENT_COLOR1,
189 DDP_COMPONENT_GAMMA,
190 DDP_COMPONENT_RDMA1,
191 DDP_COMPONENT_DPI0,
192 };
193
194 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
195 .main_path = mt2701_mtk_ddp_main,
196 .main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
197 .ext_path = mt2701_mtk_ddp_ext,
198 .ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
199 .shadow_register = true,
200 };
201
202 static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
203 .main_path = mt2712_mtk_ddp_main,
204 .main_len = ARRAY_SIZE(mt2712_mtk_ddp_main),
205 .ext_path = mt2712_mtk_ddp_ext,
206 .ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext),
> 207 .third_path = mt2712_mtk_ddp_third,
208 .third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
209 };
210
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 65211 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180526/893bcab4/attachment-0001.gz>
^ permalink raw reply
* [PATCH v3 08/15] ARM: spectre-v2: harden user aborts in kernel space
From: Tony Lindgren @ 2018-05-25 16:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525160119.GC98604@atomide.com>
* Tony Lindgren <tony@atomide.com> [180525 16:04]:
> * Russell King - ARM Linux <linux@armlinux.org.uk> [180525 15:54]:
> > On Fri, May 25, 2018 at 08:47:42AM -0700, Tony Lindgren wrote:
> > > We can now get this with the whole series applied:
> > >
> > > CPU0: Spectre v2: firmware did not set auxiliary control register
> > > IBE bit, system vulnerable
> > > CPU: Spectre v2: using ICIALLU workaround
> > >
> > > So maybe change the wording from "using %s workaround" to
> > > "chosen workaround %s"?
> > >
> > > Or I guess disabling the pr_info when not functional can
> > > be done in the later patches based on some variable set
> > > by check_spectre_auxcr() would be doable too.
> >
> > You should not be getting both messages. It looks like you're using
> > an older series - I assumed you pulled my git tree rather than the
> > patches? The public git tree isn't up to date with these changes.
>
> Yes I just fetched your git tree because it allows using
> git mergetool because of the conflicts with next. I'll apply
> manually and test again.
And testing with the correct patches in the $subject series
makes the issue go away.
Regards,
Tony
^ permalink raw reply
* [GIT PULL v2] arm64: defconfig: hisilicon config updates for v4.18
From: Wei Xu @ 2018-05-25 16:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525120140.d5gtksg62xlr6cz3@localhost>
Hi Olof,
On 2018/5/25 13:01, Olof Johansson wrote:
> On Fri, May 18, 2018 at 11:58:40AM +0100, Wei Xu wrote:
>> Hi Olof, Hi Arnd,
>>
>> Please help to pull the following changes.
>> Thanks!
>>
>> Best Regards,
>> Wei
>>
>> ---
>>
>> The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:
>>
>> Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)
>>
>> are available in the Git repository at:
>>
>> git://github.com/hisilicon/linux-hisi.git tags/hisi-defconfig-for-4.18v2
>>
>> for you to fetch changes up to 9ab1c973324566baa314f8dd4e3827e4076a8675:
>>
>> arm64: defconfig: Enable HISILICON_LPC (2018-05-11 11:39:01 +0100)
>>
>> ----------------------------------------------------------------
>> ARM64: hisilicon: defconfig updates for 4.18
>>
>> - Sync the arm64 defconfig with savedefconfig
>> - Enable the support of ethernet, eMMC, Combo/INNO phy
>> and PCIe for Hi3798CV200
>> - Enable the LPC for hip06 and hip07
>>
>> ----------------------------------------------------------------
>> John Garry (1):
>> arm64: defconfig: Enable HISILICON_LPC
>>
>> Shawn Guo (2):
>> arm64: defconfig: sync it with savedefconfig
>
> Same feedback here as for Gregory on his Marvell pull request -- please don't
> run savedefconfig since it messes up and adds a lot of conflicts for everybody.
> We'll do it in our tree right around the end of the merge window instead.
Got it.
>
> It's probably easiest to send the patches as patches so we can fix them up if
> needed, so please resend separately and we'll apply. (Or send a new pull
> request with just the two new config changes).
I will send a new pull request with the new config changes.
Thanks!
Best Regards,
Wei
>
> Thanks!
>
>
> -Olof
>
> .
>
^ permalink raw reply
* [GIT PULL v3] arm64: defconfig: hisilicon config updates for v4.18
From: Wei Xu @ 2018-05-25 16:22 UTC (permalink / raw)
To: linux-arm-kernel
Hi Olof, Hi Arnd,
Please help to pull the following changes.
Thanks!
Best Regards,
Wei
---
The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:
Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)
are available in the Git repository at:
git://github.com/hisilicon/linux-hisi.git tags/hisi-defconfig-for-4.18v3
for you to fetch changes up to 30480a849820d728c409e90bd6715d11f4071416:
arm64: defconfig: Enable HISILICON_LPC (2018-05-25 16:58:51 +0100)
----------------------------------------------------------------
ARM64: hisilicon: defconfig updates for 4.18
- Enable the support of ethernet, eMMC, Combo/INNO phy
and PCIe for Hi3798CV200
- Enable the LPC for hip06 and hip07
----------------------------------------------------------------
John Garry (1):
arm64: defconfig: Enable HISILICON_LPC
Shawn Guo (1):
arm64: defconfig: enable drivers for Poplar support
arch/arm64/configs/defconfig | 6 ++++++
1 file changed, 6 insertions(+)
^ permalink raw reply
* [PATCH v3 00/15] ARM Spectre variant 2 fixes
From: Tony Lindgren @ 2018-05-25 16:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525135938.GE17671@n2100.armlinux.org.uk>
* Russell King - ARM Linux <linux@armlinux.org.uk> [180525 07:02]:
> Third version:
> - Remove "PSCI" from the SMC version of the workaround as well.
> - Avoid reporting active workaround if the IBE bit is not set.
> - Only probe for workaround_1 on Cortex A57 and A72, or non-ARM CPUs.
> - Require features probe for workaround_1 to return zero.
> - Validation that all CPUs in the system have the same workaround status.
> - Avoid corrupting r12 in workaround_1 KVM hypervisor implementation.
Looks good to me and things still work for me. I don't really
want to count that as Tested-by though :) But feel free to add:
Boot-tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox