* [Qemu-devel] [PATCH v3 0/4] target/mips: Misc fixes and maintenance for 4.1
From: Aleksandar Markovic @ 2019-06-20 10:02 UTC (permalink / raw)
To: qemu-devel; +Cc: arikalo, amarkovic
From: Aleksandar Markovic <amarkovic@wavecomp.com>
This series contains miscelaneous fixes, improvements, and
maintainance items intended to be integrated into QEMU 4.1.
I will gradually add patches by the end of June 2019.
v2->v3:
- amendeded two patches on cleaning checkpatch warnings
v1->v2:
- added two patches on cleaning checkpatch warnings
Aleksandar Markovic (4):
MAINTAINERS: Update file items for MIPS Malta board
MAINTAINERS: Consolidate MIPS disassembler-related items
target/mips: Fix some space checkpatch errors in translate.c
target/mips: Fix if-else-switch-case arms checkpatch errors in
translate.c
MAINTAINERS | 6 +-
target/mips/translate.c | 445 +++++++++++++++++++++++++++---------------------
2 files changed, 257 insertions(+), 194 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: [RFC/PATCH] gc: run more pre-detach operations under lock
From: Duy Nguyen @ 2019-06-20 10:26 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: Jeff King, Git Mailing List, Junio C Hamano, Michael Haggerty
In-Reply-To: <87imt18a2r.fsf@evledraar.gmail.com>
On Thu, Jun 20, 2019 at 5:49 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
>
> On Wed, Jun 19 2019, Jeff King wrote:
>
> > On Wed, Jun 19, 2019 at 08:01:55PM +0200, Ævar Arnfjörð Bjarmason wrote:
> >
> >> > You could sort of avoid the problem here too with
> >> >
> >> > parallel 'git fetch --no-auto-gc {}' ::: $(git remote)
> >> > git gc --auto
> >> >
> >> > It's definitely simpler, but of course we have to manually add
> >> > --no-auto-gc in everywhere we need, so not quite as elegant.
> >> >
> >> > Actually you could already do that with 'git -c gc.auto=false fetch', I guess.
> >>
> >> The point of the 'parallel' example is to show disconnected git
> >> commands, think trying to run 'git' in a terminal while your editor
> >> asynchronously runs a polling 'fetch', or a server with multiple
> >> concurrent clients running 'gc --auto'.
> >>
> >> That's the question my RFC patch raises. As far as I can tell the
> >> approach in your patch is only needed because our locking for gc is
> >> buggy, rather than introduce the caveat that an fetch(N) operation won't
> >> do "gc" until it's finished (we may have hundreds, thousands of remotes,
> >> I use that for some more obscure use-cases) shouldn't we just fix the
> >> locking?
> >
> > I think there may be room for both approaches. Yours fixes the repeated
> > message in the more general case, but Duy's suggestion is the most
> > efficient thing.
> >
> > I agree that the "thousands of remotes" case means we might want to gc
> > in the interim. But we probably ought to do that deterministically
> > rather than hoping that the pattern of lock contention makes sense.
>
> We do it deterministically, when gc.auto thresholds et al are exceeded
> we kick one off without waiting for other stuff, if we can get the lock.
>
> I don't think this desire to just wait a bit until all the fetches are
> complete makes sense as a special-case.
>
> If, as you noted in <20190619190845.GD28145@sigill.intra.peff.net>, the
> desire is to reduce GC CPU use then you're better off just tweaking the
> limits upwards. Then you get that with everything, like when you run
> "commit" in a for-loop, not just this one special case of "fetch".
>
> We have existing potentially long-running operations like "fetch",
> "rebase" and "git svn fetch" that run "gc --auto" for their incremental
> steps, and that's a feature.
gc --auto is added at arbitrary points to help garbage collection. I
don't think it's ever intended to "do gc at this and that exact
moment", just "hey this command has taken a lot of time already (i.e.
no instant response needed) and it may have added a bit more garbage,
let's just check real quick".
> It keeps "gc --auto" dumb enough to avoid a pathological case where
> we'll have a ballooning objects dir because we figure we can run
> something "at the end", when "the end" could be hours away, and we're
> adding a new pack or hundreds of loose objects every second.
Are we optimizing for a rare (large scale) case? Such setup requires
tuning regardless to me.
> So I don't think Duy's patch is a good way to go.
This reminds me of being perfect is the enemy of the good. A normal
user has a couple remotes at most, finishing fast (enough) and in such
case it's a good idea to wait until everything is in before running
gc.
Of course making git-gc more robust wrt. parallel access is great, but
it's hard work. Dealing with locks is always tricky, especially when
new locks can come up any time.
Having said that, I don't mind if my patch gets dropped. It was just a
"hey that multiple gc output looks strange, hah the fix is quite
simple" moment for me.
--
Duy
^ permalink raw reply
* [Qemu-devel] [PATCH v3 1/4] MAINTAINERS: Update file items for MIPS Malta board
From: Aleksandar Markovic @ 2019-06-20 10:02 UTC (permalink / raw)
To: qemu-devel; +Cc: arikalo, amarkovic
In-Reply-To: <1561024929-26004-1-git-send-email-aleksandar.markovic@rt-rk.com>
From: Aleksandar Markovic <amarkovic@wavecomp.com>
hw/mips/gt64xxx_pci.c is used for Malta only, so it is logical to
place this file in Malta board section of the MAINTAINERS file.
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index acbad13..869e87b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -930,6 +930,7 @@ M: Aurelien Jarno <aurelien@aurel32.net>
R: Aleksandar Rikalo <arikalo@wavecomp.com>
S: Maintained
F: hw/mips/mips_malta.c
+F: hw/mips/gt64xxx_pci.c
F: tests/acceptance/linux_ssh_mips_malta.py
Mipssim
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2 06/10] mfd / platform: cros_ec: Reorganize platform and mfd includes
From: Chanwoo Choi @ 2019-06-20 10:28 UTC (permalink / raw)
To: Enric Balletbo i Serra, linux-kernel
Cc: gwendal, Guenter Roeck, Benson Leung, Lee Jones, kernel, dtor,
Andy Shevchenko, Mark Brown, Wolfram Sang, Neil Armstrong,
Alexandre Belloni, Benjamin Tissoires, Dmitry Torokhov,
Sebastian Reichel, Mauro Carvalho Chehab, alsa-devel,
Alessandro Zummo, linux-iio, Fabien Lahoudere, linux-i2c,
linux-rtc, Brian Norris, Gustavo A. R. Silva, Sebastian Reichel,
Rushikesh S Kadam, linux-input, Lars-Peter Clausen,
Jonathan Cameron, Peter Meerwald-Stadler, linux-media, linux-pwm,
Thierry Reding, linux-pm, Takashi Iwai, Liam Girdwood,
MyungJoo Ham, Evan Green, Hartmut Knaack, Cheng-Yi Chiang,
Jaroslav Kysela, Colin Ian King, Hans Verkuil, Jiri Kosina
In-Reply-To: <20190614163635.22413-7-enric.balletbo@collabora.com>
Hi Enric,
For extcon part,
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
Best Regards,
Chanwoo choi
On 19. 6. 15. 오전 1:36, Enric Balletbo i Serra wrote:
> There is a bit of mess between cros-ec mfd includes and platform
> includes. For example, we have a linux/mfd/cros_ec.h include that
> exports the interface implemented in platform/chrome/cros_ec_proto.c. Or
> we have a linux/mfd/cros_ec_commands.h file that is non related to the
> multifunction device (in the sense that is not exporting any function of
> the mfd device). This causes crossed includes between mfd and
> platform/chrome subsystems and makes the code difficult to read, apart
> from creating 'curious' situations where a platform/chrome driver includes
> a linux/mfd/cros_ec.h file just to get the exported functions that are
> implemented in another platform/chrome driver.
>
> In order to have a better separation on what the cros-ec multifunction
> driver does and what the cros-ec core provides move and rework the
> affected includes doing:
>
> - Move cros_ec_commands.h to include/linux/platform_data/cros_ec_commands.h
> - Get rid of the parts that are implemented in the platform/chrome/cros_ec_proto.c
> driver from include/linux/mfd/cros_ec.h to a new file
> include/linux/platform_data/cros_ec_proto.h
> - Update all the drivers with the new includes, so
> - Drivers that only need to know about the protocol include
> - linux/platform_data/cros_ec_proto.h
> - linux/platform_data/cros_ec_commands.h
> - Drivers that need to know about the cros-ec mfd device also include
> - linux/mfd/cros_ec.h
>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Acked-by: Mark Brown <broonie@kernel.org>
> Acked-by: Wolfram Sang <wsa@the-dreams.de>
> Acked-by: Neil Armstrong <narmstrong@baylibre.com>
> Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> ---
>
> Changes in v2: None
>
> drivers/extcon/extcon-usbc-cros-ec.c | 3 +-
> drivers/hid/hid-google-hammer.c | 4 +-
> drivers/i2c/busses/i2c-cros-ec-tunnel.c | 4 +-
> drivers/iio/accel/cros_ec_accel_legacy.c | 3 +-
> .../common/cros_ec_sensors/cros_ec_sensors.c | 3 +-
> .../cros_ec_sensors/cros_ec_sensors_core.c | 3 +-
> drivers/iio/light/cros_ec_light_prox.c | 3 +-
> drivers/iio/pressure/cros_ec_baro.c | 3 +-
> drivers/input/keyboard/cros_ec_keyb.c | 4 +-
> .../media/platform/cros-ec-cec/cros-ec-cec.c | 4 +-
> drivers/mfd/cros_ec_dev.c | 3 +-
> drivers/platform/chrome/cros_ec.c | 3 +-
> drivers/platform/chrome/cros_ec_debugfs.c | 3 +-
> drivers/platform/chrome/cros_ec_i2c.c | 4 +-
> drivers/platform/chrome/cros_ec_lightbar.c | 3 +-
> drivers/platform/chrome/cros_ec_lpc.c | 4 +-
> drivers/platform/chrome/cros_ec_lpc_reg.c | 4 +-
> drivers/platform/chrome/cros_ec_proto.c | 3 +-
> drivers/platform/chrome/cros_ec_rpmsg.c | 4 +-
> drivers/platform/chrome/cros_ec_spi.c | 4 +-
> drivers/platform/chrome/cros_ec_sysfs.c | 3 +-
> drivers/platform/chrome/cros_ec_trace.c | 2 +-
> drivers/platform/chrome/cros_ec_trace.h | 4 +-
> drivers/platform/chrome/cros_ec_vbc.c | 3 +-
> drivers/platform/chrome/cros_usbpd_logger.c | 5 +-
> drivers/power/supply/cros_usbpd-charger.c | 5 +-
> drivers/pwm/pwm-cros-ec.c | 4 +-
> drivers/rtc/rtc-cros-ec.c | 3 +-
> .../linux/iio/common/cros_ec_sensors_core.h | 3 +-
> include/linux/mfd/cros_ec.h | 306 -----------------
> .../{mfd => platform_data}/cros_ec_commands.h | 0
> include/linux/platform_data/cros_ec_proto.h | 315 ++++++++++++++++++
> sound/soc/codecs/cros_ec_codec.c | 4 +-
> 33 files changed, 377 insertions(+), 349 deletions(-)
> rename include/linux/{mfd => platform_data}/cros_ec_commands.h (100%)
> create mode 100644 include/linux/platform_data/cros_ec_proto.h
>
> diff --git a/drivers/extcon/extcon-usbc-cros-ec.c b/drivers/extcon/extcon-usbc-cros-ec.c
> index 43c0a936ab82..5290cc2d19d9 100644
> --- a/drivers/extcon/extcon-usbc-cros-ec.c
> +++ b/drivers/extcon/extcon-usbc-cros-ec.c
> @@ -6,10 +6,11 @@
>
> #include <linux/extcon-provider.h>
> #include <linux/kernel.h>
> -#include <linux/mfd/cros_ec.h>
> #include <linux/module.h>
> #include <linux/notifier.h>
> #include <linux/of.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> #include <linux/sched.h>
> diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c
> index ee5e0bdcf078..84f8c127ebdc 100644
> --- a/drivers/hid/hid-google-hammer.c
> +++ b/drivers/hid/hid-google-hammer.c
> @@ -16,9 +16,9 @@
> #include <linux/acpi.h>
> #include <linux/hid.h>
> #include <linux/leds.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/pm_wakeup.h>
> #include <asm/unaligned.h>
> diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> index 82bcd9a78759..c551aa96a2e3 100644
> --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
> @@ -5,8 +5,8 @@
>
> #include <linux/module.h>
> #include <linux/i2c.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
>
> diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c
> index 46bb2e421bb9..fd9a634f741e 100644
> --- a/drivers/iio/accel/cros_ec_accel_legacy.c
> +++ b/drivers/iio/accel/cros_ec_accel_legacy.c
> @@ -18,9 +18,10 @@
> #include <linux/iio/triggered_buffer.h>
> #include <linux/kernel.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> #include <linux/slab.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
>
> #define DRV_NAME "cros-ec-accel-legacy"
> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> index 17af4e0fd5f8..40dc24ff0ee5 100644
> --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> @@ -17,8 +17,9 @@
> #include <linux/iio/triggered_buffer.h>
> #include <linux/kernel.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
>
> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> index 719a0df5aeeb..fd63315399ac 100644
> --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> @@ -14,9 +14,10 @@
> #include <linux/iio/trigger_consumer.h>
> #include <linux/kernel.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> #include <linux/slab.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
>
> static char *cros_ec_loc[] = {
> diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c
> index 308ee6ff2e22..437e0eae9178 100644
> --- a/drivers/iio/light/cros_ec_light_prox.c
> +++ b/drivers/iio/light/cros_ec_light_prox.c
> @@ -15,8 +15,9 @@
> #include <linux/iio/trigger_consumer.h>
> #include <linux/kernel.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
>
> diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c
> index 034ce98d6e97..956dc01f1295 100644
> --- a/drivers/iio/pressure/cros_ec_baro.c
> +++ b/drivers/iio/pressure/cros_ec_baro.c
> @@ -15,9 +15,10 @@
> #include <linux/iio/trigger_consumer.h>
> #include <linux/kernel.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> #include <linux/slab.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
>
> /*
> diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
> index d56001181598..2b71c5a51f90 100644
> --- a/drivers/input/keyboard/cros_ec_keyb.c
> +++ b/drivers/input/keyboard/cros_ec_keyb.c
> @@ -22,8 +22,8 @@
> #include <linux/slab.h>
> #include <linux/sysrq.h>
> #include <linux/input/matrix_keypad.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
>
> #include <asm/unaligned.h>
>
> diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
> index 068df9888dbf..2e4e263a4a94 100644
> --- a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
> +++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
> @@ -16,8 +16,8 @@
> #include <linux/interrupt.h>
> #include <media/cec.h>
> #include <media/cec-notifier.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
>
> #define DRV_NAME "cros-ec-cec"
>
> diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
> index d465bcde9fc4..7572fe096c72 100644
> --- a/drivers/mfd/cros_ec_dev.c
> +++ b/drivers/mfd/cros_ec_dev.c
> @@ -19,11 +19,12 @@
>
> #include <linux/mfd/core.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> #include <linux/mod_devicetable.h>
> #include <linux/of_platform.h>
> #include <linux/platform_device.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/slab.h>
>
> #define DRV_NAME "cros-ec-dev"
> diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c
> index 11fced7917fc..9800597ccd96 100644
> --- a/drivers/platform/chrome/cros_ec.c
> +++ b/drivers/platform/chrome/cros_ec.c
> @@ -21,7 +21,8 @@
> #include <linux/interrupt.h>
> #include <linux/slab.h>
> #include <linux/module.h>
> -#include <linux/mfd/cros_ec.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/suspend.h>
> #include <asm/unaligned.h>
>
> diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
> index 4c2a27f6a6d0..b088d91be9c9 100644
> --- a/drivers/platform/chrome/cros_ec_debugfs.c
> +++ b/drivers/platform/chrome/cros_ec_debugfs.c
> @@ -8,9 +8,10 @@
> #include <linux/delay.h>
> #include <linux/fs.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/poll.h>
> #include <linux/sched.h>
> diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c
> index 6bb82dfa7dae..9bd97bc8454b 100644
> --- a/drivers/platform/chrome/cros_ec_i2c.c
> +++ b/drivers/platform/chrome/cros_ec_i2c.c
> @@ -9,8 +9,8 @@
> #include <linux/module.h>
> #include <linux/i2c.h>
> #include <linux/interrupt.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
>
> diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
> index d30a6650b0b5..caa26da2c788 100644
> --- a/drivers/platform/chrome/cros_ec_lightbar.c
> +++ b/drivers/platform/chrome/cros_ec_lightbar.c
> @@ -9,8 +9,9 @@
> #include <linux/fs.h>
> #include <linux/kobject.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/sched.h>
> #include <linux/types.h>
> diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
> index 2c7e654cf89c..0c976e95998a 100644
> --- a/drivers/platform/chrome/cros_ec_lpc.c
> +++ b/drivers/platform/chrome/cros_ec_lpc.c
> @@ -16,9 +16,9 @@
> #include <linux/delay.h>
> #include <linux/io.h>
> #include <linux/interrupt.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/printk.h>
> #include <linux/suspend.h>
> diff --git a/drivers/platform/chrome/cros_ec_lpc_reg.c b/drivers/platform/chrome/cros_ec_lpc_reg.c
> index 0f5cd0ac8b49..dec9a779e209 100644
> --- a/drivers/platform/chrome/cros_ec_lpc_reg.c
> +++ b/drivers/platform/chrome/cros_ec_lpc_reg.c
> @@ -4,8 +4,8 @@
> // Copyright (C) 2016 Google, Inc
>
> #include <linux/io.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
>
> #include "cros_ec_lpc_mec.h"
>
> diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
> index 3d2325197a68..f659f96bda12 100644
> --- a/drivers/platform/chrome/cros_ec_proto.c
> +++ b/drivers/platform/chrome/cros_ec_proto.c
> @@ -3,10 +3,11 @@
> //
> // Copyright (C) 2015 Google, Inc
>
> -#include <linux/mfd/cros_ec.h>
> #include <linux/delay.h>
> #include <linux/device.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/slab.h>
> #include <asm/unaligned.h>
>
> diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c b/drivers/platform/chrome/cros_ec_rpmsg.c
> index 520e507bfa54..9633e5417686 100644
> --- a/drivers/platform/chrome/cros_ec_rpmsg.c
> +++ b/drivers/platform/chrome/cros_ec_rpmsg.c
> @@ -6,9 +6,9 @@
> #include <linux/delay.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/of.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/rpmsg.h>
> #include <linux/slab.h>
> diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c
> index 02f9e8257581..a4167dfd85bf 100644
> --- a/drivers/platform/chrome/cros_ec_spi.c
> +++ b/drivers/platform/chrome/cros_ec_spi.c
> @@ -6,9 +6,9 @@
> #include <linux/delay.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/of.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> #include <linux/spi/spi.h>
> diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c
> index fe0b7614ae1b..0caeb8d0989d 100644
> --- a/drivers/platform/chrome/cros_ec_sysfs.c
> +++ b/drivers/platform/chrome/cros_ec_sysfs.c
> @@ -9,8 +9,9 @@
> #include <linux/fs.h>
> #include <linux/kobject.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/printk.h>
> #include <linux/slab.h>
> diff --git a/drivers/platform/chrome/cros_ec_trace.c b/drivers/platform/chrome/cros_ec_trace.c
> index 0a76412095a9..6f80ff4532ae 100644
> --- a/drivers/platform/chrome/cros_ec_trace.c
> +++ b/drivers/platform/chrome/cros_ec_trace.c
> @@ -6,7 +6,7 @@
> #define TRACE_SYMBOL(a) {a, #a}
>
> // Generate the list using the following script:
> -// sed -n 's/^#define \(EC_CMD_[[:alnum:]_]*\)\s.*/\tTRACE_SYMBOL(\1), \\/p' include/linux/mfd/cros_ec_commands.h
> +// sed -n 's/^#define \(EC_CMD_[[:alnum:]_]*\)\s.*/\tTRACE_SYMBOL(\1), \\/p' include/linux/platform_data/cros_ec_commands.h
> #define EC_CMDS \
> TRACE_SYMBOL(EC_CMD_PROTO_VERSION), \
> TRACE_SYMBOL(EC_CMD_HELLO), \
> diff --git a/drivers/platform/chrome/cros_ec_trace.h b/drivers/platform/chrome/cros_ec_trace.h
> index 7ae3b89c78b9..0dd4df30fa89 100644
> --- a/drivers/platform/chrome/cros_ec_trace.h
> +++ b/drivers/platform/chrome/cros_ec_trace.h
> @@ -11,8 +11,10 @@
> #if !defined(_CROS_EC_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
> #define _CROS_EC_TRACE_H_
>
> +#include <linux/bits.h>
> #include <linux/types.h>
> -#include <linux/mfd/cros_ec.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
>
> #include <linux/tracepoint.h>
>
> diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c
> index 8392a1ec33a7..cffe119e7a7a 100644
> --- a/drivers/platform/chrome/cros_ec_vbc.c
> +++ b/drivers/platform/chrome/cros_ec_vbc.c
> @@ -7,8 +7,9 @@
> #include <linux/of.h>
> #include <linux/platform_device.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/slab.h>
>
> #define DRV_NAME "cros-ec-vbc"
> diff --git a/drivers/platform/chrome/cros_usbpd_logger.c b/drivers/platform/chrome/cros_usbpd_logger.c
> index 7c7b267626a0..c549a9b49b56 100644
> --- a/drivers/platform/chrome/cros_usbpd_logger.c
> +++ b/drivers/platform/chrome/cros_usbpd_logger.c
> @@ -6,10 +6,11 @@
> */
>
> #include <linux/ktime.h>
> -#include <linux/math64.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/math64.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/rtc.h>
>
> diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c
> index 7e9c3984ef6a..ed8eca28c195 100644
> --- a/drivers/power/supply/cros_usbpd-charger.c
> +++ b/drivers/power/supply/cros_usbpd-charger.c
> @@ -5,9 +5,10 @@
> * Copyright (c) 2014 - 2018 Google, Inc
> */
>
> -#include <linux/module.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/power_supply.h>
> #include <linux/slab.h>
> diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
> index 98f6ac6cf6ab..85bea2d40b7d 100644
> --- a/drivers/pwm/pwm-cros-ec.c
> +++ b/drivers/pwm/pwm-cros-ec.c
> @@ -6,8 +6,8 @@
> */
>
> #include <linux/module.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/pwm.h>
> #include <linux/slab.h>
> diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
> index 4d6bf9304ceb..6909e01936d9 100644
> --- a/drivers/rtc/rtc-cros-ec.c
> +++ b/drivers/rtc/rtc-cros-ec.c
> @@ -6,8 +6,9 @@
>
> #include <linux/kernel.h>
> #include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <linux/rtc.h>
> #include <linux/slab.h>
> diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h
> index ce16445411ac..8a91669f5bed 100644
> --- a/include/linux/iio/common/cros_ec_sensors_core.h
> +++ b/include/linux/iio/common/cros_ec_sensors_core.h
> @@ -18,7 +18,8 @@
>
> #include <linux/iio/iio.h>
> #include <linux/irqreturn.h>
> -#include <linux/mfd/cros_ec.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
>
> enum {
> CROS_EC_SENSOR_X,
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 2a1372d167b9..e0bae49535e1 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -16,184 +16,7 @@
> #ifndef __LINUX_MFD_CROS_EC_H
> #define __LINUX_MFD_CROS_EC_H
>
> -#include <linux/cdev.h>
> #include <linux/device.h>
> -#include <linux/notifier.h>
> -#include <linux/mfd/cros_ec_commands.h>
> -#include <linux/mutex.h>
> -
> -#define CROS_EC_DEV_NAME "cros_ec"
> -#define CROS_EC_DEV_FP_NAME "cros_fp"
> -#define CROS_EC_DEV_PD_NAME "cros_pd"
> -#define CROS_EC_DEV_TP_NAME "cros_tp"
> -#define CROS_EC_DEV_ISH_NAME "cros_ish"
> -
> -/*
> - * The EC is unresponsive for a time after a reboot command. Add a
> - * simple delay to make sure that the bus stays locked.
> - */
> -#define EC_REBOOT_DELAY_MS 50
> -
> -/*
> - * Max bus-specific overhead incurred by request/responses.
> - * I2C requires 1 additional byte for requests.
> - * I2C requires 2 additional bytes for responses.
> - * SPI requires up to 32 additional bytes for responses.
> - */
> -#define EC_PROTO_VERSION_UNKNOWN 0
> -#define EC_MAX_REQUEST_OVERHEAD 1
> -#define EC_MAX_RESPONSE_OVERHEAD 32
> -
> -/*
> - * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
> - */
> -enum {
> - EC_MSG_TX_HEADER_BYTES = 3,
> - EC_MSG_TX_TRAILER_BYTES = 1,
> - EC_MSG_TX_PROTO_BYTES = EC_MSG_TX_HEADER_BYTES +
> - EC_MSG_TX_TRAILER_BYTES,
> - EC_MSG_RX_PROTO_BYTES = 3,
> -
> - /* Max length of messages for proto 2*/
> - EC_PROTO2_MSG_BYTES = EC_PROTO2_MAX_PARAM_SIZE +
> - EC_MSG_TX_PROTO_BYTES,
> -
> - EC_MAX_MSG_BYTES = 64 * 1024,
> -};
> -
> -/**
> - * struct cros_ec_command - Information about a ChromeOS EC command.
> - * @version: Command version number (often 0).
> - * @command: Command to send (EC_CMD_...).
> - * @outsize: Outgoing length in bytes.
> - * @insize: Max number of bytes to accept from the EC.
> - * @result: EC's response to the command (separate from communication failure).
> - * @data: Where to put the incoming data from EC and outgoing data to EC.
> - */
> -struct cros_ec_command {
> - uint32_t version;
> - uint32_t command;
> - uint32_t outsize;
> - uint32_t insize;
> - uint32_t result;
> - uint8_t data[0];
> -};
> -
> -/**
> - * struct cros_ec_device - Information about a ChromeOS EC device.
> - * @phys_name: Name of physical comms layer (e.g. 'i2c-4').
> - * @dev: Device pointer for physical comms device
> - * @was_wake_device: True if this device was set to wake the system from
> - * sleep at the last suspend.
> - * @cros_class: The class structure for this device.
> - * @cmd_readmem: Direct read of the EC memory-mapped region, if supported.
> - * @offset: Is within EC_LPC_ADDR_MEMMAP region.
> - * @bytes: Number of bytes to read. zero means "read a string" (including
> - * the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be
> - * read. Caller must ensure that the buffer is large enough for the
> - * result when reading a string.
> - * @max_request: Max size of message requested.
> - * @max_response: Max size of message response.
> - * @max_passthru: Max sice of passthru message.
> - * @proto_version: The protocol version used for this device.
> - * @priv: Private data.
> - * @irq: Interrupt to use.
> - * @id: Device id.
> - * @din: Input buffer (for data from EC). This buffer will always be
> - * dword-aligned and include enough space for up to 7 word-alignment
> - * bytes also, so we can ensure that the body of the message is always
> - * dword-aligned (64-bit). We use this alignment to keep ARM and x86
> - * happy. Probably word alignment would be OK, there might be a small
> - * performance advantage to using dword.
> - * @dout: Output buffer (for data to EC). This buffer will always be
> - * dword-aligned and include enough space for up to 7 word-alignment
> - * bytes also, so we can ensure that the body of the message is always
> - * dword-aligned (64-bit). We use this alignment to keep ARM and x86
> - * happy. Probably word alignment would be OK, there might be a small
> - * performance advantage to using dword.
> - * @din_size: Size of din buffer to allocate (zero to use static din).
> - * @dout_size: Size of dout buffer to allocate (zero to use static dout).
> - * @wake_enabled: True if this device can wake the system from sleep.
> - * @suspended: True if this device had been suspended.
> - * @cmd_xfer: Send command to EC and get response.
> - * Returns the number of bytes received if the communication
> - * succeeded, but that doesn't mean the EC was happy with the
> - * command. The caller should check msg.result for the EC's result
> - * code.
> - * @pkt_xfer: Send packet to EC and get response.
> - * @lock: One transaction at a time.
> - * @mkbp_event_supported: True if this EC supports the MKBP event protocol.
> - * @host_sleep_v1: True if this EC supports the sleep v1 command.
> - * @event_notifier: Interrupt event notifier for transport devices.
> - * @event_data: Raw payload transferred with the MKBP event.
> - * @event_size: Size in bytes of the event data.
> - * @host_event_wake_mask: Mask of host events that cause wake from suspend.
> - * @ec: The platform_device used by the mfd driver to interface with the
> - * main EC.
> - * @pd: The platform_device used by the mfd driver to interface with the
> - * PD behind an EC.
> - */
> -struct cros_ec_device {
> - /* These are used by other drivers that want to talk to the EC */
> - const char *phys_name;
> - struct device *dev;
> - bool was_wake_device;
> - struct class *cros_class;
> - int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
> - unsigned int bytes, void *dest);
> -
> - /* These are used to implement the platform-specific interface */
> - u16 max_request;
> - u16 max_response;
> - u16 max_passthru;
> - u16 proto_version;
> - void *priv;
> - int irq;
> - u8 *din;
> - u8 *dout;
> - int din_size;
> - int dout_size;
> - bool wake_enabled;
> - bool suspended;
> - int (*cmd_xfer)(struct cros_ec_device *ec,
> - struct cros_ec_command *msg);
> - int (*pkt_xfer)(struct cros_ec_device *ec,
> - struct cros_ec_command *msg);
> - struct mutex lock;
> - bool mkbp_event_supported;
> - bool host_sleep_v1;
> - struct blocking_notifier_head event_notifier;
> -
> - struct ec_response_get_next_event_v1 event_data;
> - int event_size;
> - u32 host_event_wake_mask;
> -
> - /* The platform devices used by the mfd driver */
> - struct platform_device *ec;
> - struct platform_device *pd;
> -};
> -
> -/**
> - * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information.
> - * @sensor_num: Id of the sensor, as reported by the EC.
> - */
> -struct cros_ec_sensor_platform {
> - u8 sensor_num;
> -};
> -
> -/**
> - * struct cros_ec_platform - ChromeOS EC platform information.
> - * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
> - * used in /dev/ and sysfs.
> - * @cmd_offset: Offset to apply for each command. Set when
> - * registering a device behind another one.
> - */
> -struct cros_ec_platform {
> - const char *ec_name;
> - u16 cmd_offset;
> -};
> -
> -struct cros_ec_debugfs;
>
> /**
> * struct cros_ec_dev - ChromeOS EC device entry point.
> @@ -217,133 +40,4 @@ struct cros_ec_dev {
>
> #define to_cros_ec_dev(dev) container_of(dev, struct cros_ec_dev, class_dev)
>
> -/**
> - * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
> - * @ec_dev: Device to suspend.
> - *
> - * This can be called by drivers to handle a suspend event.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_suspend(struct cros_ec_device *ec_dev);
> -
> -/**
> - * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
> - * @ec_dev: Device to resume.
> - *
> - * This can be called by drivers to handle a resume event.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_resume(struct cros_ec_device *ec_dev);
> -
> -/**
> - * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
> - * @ec_dev: Device to register.
> - * @msg: Message to write.
> - *
> - * This is intended to be used by all ChromeOS EC drivers, but at present
> - * only SPI uses it. Once LPC uses the same protocol it can start using it.
> - * I2C could use it now, with a refactor of the existing code.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
> - struct cros_ec_command *msg);
> -
> -/**
> - * cros_ec_check_result() - Check ec_msg->result.
> - * @ec_dev: EC device.
> - * @msg: Message to check.
> - *
> - * This is used by ChromeOS EC drivers to check the ec_msg->result for
> - * errors and to warn about them.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_check_result(struct cros_ec_device *ec_dev,
> - struct cros_ec_command *msg);
> -
> -/**
> - * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
> - * @ec_dev: EC device.
> - * @msg: Message to write.
> - *
> - * Call this to send a command to the ChromeOS EC. This should be used
> - * instead of calling the EC's cmd_xfer() callback directly.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
> - struct cros_ec_command *msg);
> -
> -/**
> - * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
> - * @ec_dev: EC device.
> - * @msg: Message to write.
> - *
> - * This function is identical to cros_ec_cmd_xfer, except it returns success
> - * status only if both the command was transmitted successfully and the EC
> - * replied with success status. It's not necessary to check msg->result when
> - * using this function.
> - *
> - * Return: The number of bytes transferred on success or negative error code.
> - */
> -int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
> - struct cros_ec_command *msg);
> -
> -/**
> - * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
> - * @ec_dev: Device to register.
> - *
> - * Before calling this, allocate a pointer to a new device and then fill
> - * in all the fields up to the --private-- marker.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_register(struct cros_ec_device *ec_dev);
> -
> -/**
> - * cros_ec_unregister() - Remove a ChromeOS EC.
> - * @ec_dev: Device to unregister.
> - *
> - * Call this to deregister a ChromeOS EC, then clean up any private data.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_unregister(struct cros_ec_device *ec_dev);
> -
> -/**
> - * cros_ec_query_all() - Query the protocol version supported by the
> - * ChromeOS EC.
> - * @ec_dev: Device to register.
> - *
> - * Return: 0 on success or negative error code.
> - */
> -int cros_ec_query_all(struct cros_ec_device *ec_dev);
> -
> -/**
> - * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
> - * @ec_dev: Device to fetch event from.
> - * @wake_event: Pointer to a bool set to true upon return if the event might be
> - * treated as a wake event. Ignored if null.
> - *
> - * Return: negative error code on errors; 0 for no data; or else number of
> - * bytes received (i.e., an event was retrieved successfully). Event types are
> - * written out to @ec_dev->event_data.event_type on success.
> - */
> -int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
> -
> -/**
> - * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
> - * @ec_dev: Device to fetch event from.
> - *
> - * When MKBP is supported, when the EC raises an interrupt, we collect the
> - * events raised and call the functions in the ec notifier. This function
> - * is a helper to know which events are raised.
> - *
> - * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
> - */
> -u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
> -
> #endif /* __LINUX_MFD_CROS_EC_H */
> diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
> similarity index 100%
> rename from include/linux/mfd/cros_ec_commands.h
> rename to include/linux/platform_data/cros_ec_commands.h
> diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h
> new file mode 100644
> index 000000000000..34dd9e5c1779
> --- /dev/null
> +++ b/include/linux/platform_data/cros_ec_proto.h
> @@ -0,0 +1,315 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * ChromeOS Embedded Controller protocol interface.
> + *
> + * Copyright (C) 2012 Google, Inc
> + */
> +
> +#ifndef __LINUX_CROS_EC_PROTO_H
> +#define __LINUX_CROS_EC_PROTO_H
> +
> +#include <linux/device.h>
> +#include <linux/mutex.h>
> +#include <linux/notifier.h>
> +
> +#define CROS_EC_DEV_NAME "cros_ec"
> +#define CROS_EC_DEV_FP_NAME "cros_fp"
> +#define CROS_EC_DEV_ISH_NAME "cros_ish"
> +#define CROS_EC_DEV_PD_NAME "cros_pd"
> +#define CROS_EC_DEV_TP_NAME "cros_tp"
> +
> +/*
> + * The EC is unresponsive for a time after a reboot command. Add a
> + * simple delay to make sure that the bus stays locked.
> + */
> +#define EC_REBOOT_DELAY_MS 50
> +
> +/*
> + * Max bus-specific overhead incurred by request/responses.
> + * I2C requires 1 additional byte for requests.
> + * I2C requires 2 additional bytes for responses.
> + * SPI requires up to 32 additional bytes for responses.
> + */
> +#define EC_PROTO_VERSION_UNKNOWN 0
> +#define EC_MAX_REQUEST_OVERHEAD 1
> +#define EC_MAX_RESPONSE_OVERHEAD 32
> +
> +/*
> + * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
> + */
> +enum {
> + EC_MSG_TX_HEADER_BYTES = 3,
> + EC_MSG_TX_TRAILER_BYTES = 1,
> + EC_MSG_TX_PROTO_BYTES = EC_MSG_TX_HEADER_BYTES +
> + EC_MSG_TX_TRAILER_BYTES,
> + EC_MSG_RX_PROTO_BYTES = 3,
> +
> + /* Max length of messages for proto 2*/
> + EC_PROTO2_MSG_BYTES = EC_PROTO2_MAX_PARAM_SIZE +
> + EC_MSG_TX_PROTO_BYTES,
> +
> + EC_MAX_MSG_BYTES = 64 * 1024,
> +};
> +
> +/**
> + * struct cros_ec_command - Information about a ChromeOS EC command.
> + * @version: Command version number (often 0).
> + * @command: Command to send (EC_CMD_...).
> + * @outsize: Outgoing length in bytes.
> + * @insize: Max number of bytes to accept from the EC.
> + * @result: EC's response to the command (separate from communication failure).
> + * @data: Where to put the incoming data from EC and outgoing data to EC.
> + */
> +struct cros_ec_command {
> + uint32_t version;
> + uint32_t command;
> + uint32_t outsize;
> + uint32_t insize;
> + uint32_t result;
> + uint8_t data[0];
> +};
> +
> +/**
> + * struct cros_ec_device - Information about a ChromeOS EC device.
> + * @phys_name: Name of physical comms layer (e.g. 'i2c-4').
> + * @dev: Device pointer for physical comms device
> + * @was_wake_device: True if this device was set to wake the system from
> + * sleep at the last suspend.
> + * @cros_class: The class structure for this device.
> + * @cmd_readmem: Direct read of the EC memory-mapped region, if supported.
> + * @offset: Is within EC_LPC_ADDR_MEMMAP region.
> + * @bytes: Number of bytes to read. zero means "read a string" (including
> + * the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be
> + * read. Caller must ensure that the buffer is large enough for the
> + * result when reading a string.
> + * @max_request: Max size of message requested.
> + * @max_response: Max size of message response.
> + * @max_passthru: Max sice of passthru message.
> + * @proto_version: The protocol version used for this device.
> + * @priv: Private data.
> + * @irq: Interrupt to use.
> + * @id: Device id.
> + * @din: Input buffer (for data from EC). This buffer will always be
> + * dword-aligned and include enough space for up to 7 word-alignment
> + * bytes also, so we can ensure that the body of the message is always
> + * dword-aligned (64-bit). We use this alignment to keep ARM and x86
> + * happy. Probably word alignment would be OK, there might be a small
> + * performance advantage to using dword.
> + * @dout: Output buffer (for data to EC). This buffer will always be
> + * dword-aligned and include enough space for up to 7 word-alignment
> + * bytes also, so we can ensure that the body of the message is always
> + * dword-aligned (64-bit). We use this alignment to keep ARM and x86
> + * happy. Probably word alignment would be OK, there might be a small
> + * performance advantage to using dword.
> + * @din_size: Size of din buffer to allocate (zero to use static din).
> + * @dout_size: Size of dout buffer to allocate (zero to use static dout).
> + * @wake_enabled: True if this device can wake the system from sleep.
> + * @suspended: True if this device had been suspended.
> + * @cmd_xfer: Send command to EC and get response.
> + * Returns the number of bytes received if the communication
> + * succeeded, but that doesn't mean the EC was happy with the
> + * command. The caller should check msg.result for the EC's result
> + * code.
> + * @pkt_xfer: Send packet to EC and get response.
> + * @lock: One transaction at a time.
> + * @mkbp_event_supported: True if this EC supports the MKBP event protocol.
> + * @host_sleep_v1: True if this EC supports the sleep v1 command.
> + * @event_notifier: Interrupt event notifier for transport devices.
> + * @event_data: Raw payload transferred with the MKBP event.
> + * @event_size: Size in bytes of the event data.
> + * @host_event_wake_mask: Mask of host events that cause wake from suspend.
> + * @ec: The platform_device used by the mfd driver to interface with the
> + * main EC.
> + * @pd: The platform_device used by the mfd driver to interface with the
> + * PD behind an EC.
> + */
> +struct cros_ec_device {
> + /* These are used by other drivers that want to talk to the EC */
> + const char *phys_name;
> + struct device *dev;
> + bool was_wake_device;
> + struct class *cros_class;
> + int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
> + unsigned int bytes, void *dest);
> +
> + /* These are used to implement the platform-specific interface */
> + u16 max_request;
> + u16 max_response;
> + u16 max_passthru;
> + u16 proto_version;
> + void *priv;
> + int irq;
> + u8 *din;
> + u8 *dout;
> + int din_size;
> + int dout_size;
> + bool wake_enabled;
> + bool suspended;
> + int (*cmd_xfer)(struct cros_ec_device *ec,
> + struct cros_ec_command *msg);
> + int (*pkt_xfer)(struct cros_ec_device *ec,
> + struct cros_ec_command *msg);
> + struct mutex lock;
> + bool mkbp_event_supported;
> + bool host_sleep_v1;
> + struct blocking_notifier_head event_notifier;
> +
> + struct ec_response_get_next_event_v1 event_data;
> + int event_size;
> + u32 host_event_wake_mask;
> +
> + /* The platform devices used by the mfd driver */
> + struct platform_device *ec;
> + struct platform_device *pd;
> +};
> +
> +/**
> + * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information.
> + * @sensor_num: Id of the sensor, as reported by the EC.
> + */
> +struct cros_ec_sensor_platform {
> + u8 sensor_num;
> +};
> +
> +/**
> + * struct cros_ec_platform - ChromeOS EC platform information.
> + * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
> + * used in /dev/ and sysfs.
> + * @cmd_offset: Offset to apply for each command. Set when
> + * registering a device behind another one.
> + */
> +struct cros_ec_platform {
> + const char *ec_name;
> + u16 cmd_offset;
> +};
> +
> +/**
> + * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
> + * @ec_dev: Device to suspend.
> + *
> + * This can be called by drivers to handle a suspend event.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_suspend(struct cros_ec_device *ec_dev);
> +
> +/**
> + * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
> + * @ec_dev: Device to resume.
> + *
> + * This can be called by drivers to handle a resume event.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_resume(struct cros_ec_device *ec_dev);
> +
> +/**
> + * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
> + * @ec_dev: Device to register.
> + * @msg: Message to write.
> + *
> + * This is intended to be used by all ChromeOS EC drivers, but at present
> + * only SPI uses it. Once LPC uses the same protocol it can start using it.
> + * I2C could use it now, with a refactor of the existing code.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
> + struct cros_ec_command *msg);
> +
> +/**
> + * cros_ec_check_result() - Check ec_msg->result.
> + * @ec_dev: EC device.
> + * @msg: Message to check.
> + *
> + * This is used by ChromeOS EC drivers to check the ec_msg->result for
> + * errors and to warn about them.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_check_result(struct cros_ec_device *ec_dev,
> + struct cros_ec_command *msg);
> +
> +/**
> + * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
> + * @ec_dev: EC device.
> + * @msg: Message to write.
> + *
> + * Call this to send a command to the ChromeOS EC. This should be used
> + * instead of calling the EC's cmd_xfer() callback directly.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
> + struct cros_ec_command *msg);
> +
> +/**
> + * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
> + * @ec_dev: EC device.
> + * @msg: Message to write.
> + *
> + * This function is identical to cros_ec_cmd_xfer, except it returns success
> + * status only if both the command was transmitted successfully and the EC
> + * replied with success status. It's not necessary to check msg->result when
> + * using this function.
> + *
> + * Return: The number of bytes transferred on success or negative error code.
> + */
> +int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
> + struct cros_ec_command *msg);
> +
> +/**
> + * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
> + * @ec_dev: Device to register.
> + *
> + * Before calling this, allocate a pointer to a new device and then fill
> + * in all the fields up to the --private-- marker.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_register(struct cros_ec_device *ec_dev);
> +
> +/**
> + * cros_ec_unregister() - Remove a ChromeOS EC.
> + * @ec_dev: Device to unregister.
> + *
> + * Call this to deregister a ChromeOS EC, then clean up any private data.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_unregister(struct cros_ec_device *ec_dev);
> +
> +/**
> + * cros_ec_query_all() - Query the protocol version supported by the
> + * ChromeOS EC.
> + * @ec_dev: Device to register.
> + *
> + * Return: 0 on success or negative error code.
> + */
> +int cros_ec_query_all(struct cros_ec_device *ec_dev);
> +
> +/**
> + * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
> + * @ec_dev: Device to fetch event from.
> + * @wake_event: Pointer to a bool set to true upon return if the event might be
> + * treated as a wake event. Ignored if null.
> + *
> + * Return: negative error code on errors; 0 for no data; or else number of
> + * bytes received (i.e., an event was retrieved successfully). Event types are
> + * written out to @ec_dev->event_data.event_type on success.
> + */
> +int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
> +
> +/**
> + * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
> + * @ec_dev: Device to fetch event from.
> + *
> + * When MKBP is supported, when the EC raises an interrupt, we collect the
> + * events raised and call the functions in the ec notifier. This function
> + * is a helper to know which events are raised.
> + *
> + * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
> + */
> +u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
> +
> +#endif /* __LINUX_CROS_EC_PROTO_H */
> diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c
> index 87830ed5ebf4..79bb4081d3c2 100644
> --- a/sound/soc/codecs/cros_ec_codec.c
> +++ b/sound/soc/codecs/cros_ec_codec.c
> @@ -9,9 +9,9 @@
> #include <linux/delay.h>
> #include <linux/device.h>
> #include <linux/kernel.h>
> -#include <linux/mfd/cros_ec.h>
> -#include <linux/mfd/cros_ec_commands.h>
> #include <linux/module.h>
> +#include <linux/platform_data/cros_ec_commands.h>
> +#include <linux/platform_data/cros_ec_proto.h>
> #include <linux/platform_device.h>
> #include <sound/pcm.h>
> #include <sound/pcm_params.h>
>
--
Best Regards,
Chanwoo Choi
Samsung Electronics
^ permalink raw reply
* Re: [PATCH v1 2/5] coresight: etm4x: use explicit barriers on enable/disable
From: Andrew Murray @ 2019-06-20 10:25 UTC (permalink / raw)
To: Suzuki K Poulose; +Cc: alexander.shishkin, linux-arm-kernel, mathieu.poirier
In-Reply-To: <e5b288ad-91bd-8854-469a-bee44bf202cf@arm.com>
On Wed, Jun 19, 2019 at 09:32:56AM +0100, Suzuki K Poulose wrote:
>
>
> On 18/06/2019 23:34, Mathieu Poirier wrote:
> > On Tue, Jun 18, 2019 at 01:54:30PM +0100, Andrew Murray wrote:
> > > Synchronization is recommended before disabling the trace registers
> > > to prevent any start or stop points being speculative at the point
> > > of disabling the unit (section 7.3.77 of ARM IHI 0064D).
> > >
> > > Synchronization is also recommended after programming the trace
> > > registers to ensure all updates are committed prior to normal code
> > > resuming (section 4.3.7 of ARM IHI 0064D).
> > >
> > > Let's ensure these syncronization points are present in the code
> > > and clearly commented.
> > >
> > > Note that we could rely on the barriers in CS_LOCK and
> > > coresight_disclaim_device_unlocked or the context switch to user
> > > space - however coresight may be of use in the kernel.
> > >
> > > Signed-off-by: Andrew Murray <andrew.murray@arm.com>
> > > ---
> > > drivers/hwtracing/coresight/coresight-etm4x.c | 7 ++++++-
> > > 1 file changed, 6 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
> > > index da7cf74d612b..ae623415c431 100644
> > > --- a/drivers/hwtracing/coresight/coresight-etm4x.c
> > > +++ b/drivers/hwtracing/coresight/coresight-etm4x.c
> > > @@ -187,6 +187,10 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> > > dev_err(drvdata->dev,
> > > "timeout while waiting for Idle Trace Status\n");
> > > + /* As recommended by 4.3.7 of ARM IHI 0064D */
> > > + dsb(sy);
> > > + isb();
> > > +
>
> I think this should go to stable. Please Cc stable in the next version. or
> alternately you may add a "fixes" tag.
Sure I'll CC stable.
>
> > > done:
> > > CS_LOCK(drvdata->base);
> > > @@ -453,7 +457,8 @@ static void etm4_disable_hw(void *info)
> > > control &= ~0x1;
> > > /* make sure everything completes before disabling */
> > > - mb();
> > > + /* As recommended by 7.3.77 of ARM IHI 0064D */
> > > + dsb(sy);
> >
> > As far as I can tell mb() is equal to dsb(sy).
>
> Yes, however, given that etm4x is for armv8 cores, having the explicit dsb()
> make sense to avoid someone looking up again to see what mb() translates to.
> I suggested the dsb() over mb(), so that it is evident to someone who is trying
> to correlate the TRM vs the code.
As the TRM explictly mentions dsb, I'd prefer to explictly do this in the code
rather than rely on whatever mb will be in the future.
Thanks,
Andrew Murray
>
>
> Cheers
> Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V6 00/27] Enable Tegra PCIe root port features
From: Thierry Reding @ 2019-06-20 10:25 UTC (permalink / raw)
To: Lorenzo Pieralisi, Bjorn Helgaas
Cc: Manikanta Maddireddy, robh+dt, mark.rutland, jonathanh, vidyas,
linux-tegra, linux-pci, devicetree
In-Reply-To: <20190618180206.4908-1-mmaddireddy@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 3600 bytes --]
On Tue, Jun 18, 2019 at 11:31:39PM +0530, Manikanta Maddireddy wrote:
> This series of patches adds,
> - Tegra root port features like Gen2, AER, etc
> - Power and perf optimizations
> - Fixes like "power up sequence", "dev_err prints", etc
>
> This series of patches are tested on Tegra186 based Jetson-TX2, Tegra210
> based Jetson-TX1, T124 based Jetson-TK1, Tegra20 and Tegra30 platforms.
>
> Changes from V5 to V6:
> - Patch [V4, 20/27]: Replaced pcie_pme_disable_msi() with no_msi quirk
>
> Changes from V4 to V5:
> - Patch [V4, 4/28]: Added blank line before block style comment
> - Patch [V4, 22/28]: "Access endpoint config only if PCIe link is up"
> patch is dropped
> - Patch [V4, 27/28]:
> * Updated reset gpio toggle logic to reflect active low usage
> * Replaced kasprintf() with devm_kasprintf()
> * Updated commit message with more information.
>
> Changes from V3 to V4:
> - Patch [V3,27/29] is dropped
> - Patch [V3,28/29]: devm_gpiod_get_from_of_node() is directly used in
> pci-tegra driver instead of of_get_pci* wrapper function defined in
> Patch [V3,27/29].
>
> Manikanta Maddireddy (27):
> soc/tegra: pmc: Export tegra_powergate_power_on()
> PCI: tegra: Handle failure cases in tegra_pcie_power_on()
> PCI: tegra: Rearrange Tegra PCIe driver functions
> PCI: tegra: Mask AFI_INTR in runtime suspend
> PCI: tegra: Fix PCIe host power up sequence
> PCI: tegra: Add PCIe Gen2 link speed support
> PCI: tegra: Advertise PCIe Advanced Error Reporting (AER) capability
> PCI: tegra: Program UPHY electrical settings for Tegra210
> PCI: tegra: Enable opportunistic UpdateFC and ACK
> PCI: tegra: Disable AFI dynamic clock gating
> PCI: tegra: Process pending DLL transactions before entering L1 or L2
> PCI: tegra: Enable PCIe xclk clock clamping
> PCI: tegra: Increase the deskew retry time
> PCI: tegra: Add SW fixup for RAW violations
> PCI: tegra: Update flow control timer frequency in Tegra210
> PCI: tegra: Set target speed as Gen1 before starting LTSSM
> PCI: tegra: Fix PLLE power down issue due to CLKREQ# signal
> PCI: tegra: Program AFI_CACHE* registers only for Tegra20
> PCI: tegra: Change PRSNT_SENSE IRQ log to debug
> PCI: tegra: Disable MSI for Tegra PCIe root port
> PCI: tegra: Add AFI_PEX2_CTRL reg offset as part of soc struct
> dt-bindings: pci: tegra: Document PCIe DPD pinctrl optional prop
> arm64: tegra: Add PEX DPD states as pinctrl properties
> PCI: tegra: Put PEX CLK & BIAS pads in DPD mode
> PCI: Add DT binding for "reset-gpios" property
> PCI: tegra: Add support for GPIO based PERST#
> PCI: tegra: Change link retry log level to debug
Hi Lorenzo, Bjorn,
There's a build-time dependency from the PCI patches on patch 1 of this
series. I've already Acked that, so I think you should take it through
the PCI tree along with the rest of the series.
The only patch that I picked up is the DT change in patch 23, which is
decoupled from the others via DT, though the data that it adds to DT
will be used in patch 24.
Does that sound good to you?
Thierry
>
> .../bindings/pci/nvidia,tegra20-pcie.txt | 8 +
> Documentation/devicetree/bindings/pci/pci.txt | 3 +
> arch/arm64/boot/dts/nvidia/tegra210.dtsi | 19 +
> drivers/pci/controller/pci-tegra.c | 578 +++++++++++++++---
> drivers/pci/quirks.c | 39 ++
> drivers/soc/tegra/pmc.c | 1 +
> 6 files changed, 568 insertions(+), 80 deletions(-)
>
> --
> 2.17.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 1/5] usb: xhci: add firmware loader for uPD720201 and uPD720202 w/o ROM
From: Vinod Koul @ 2019-06-20 10:21 UTC (permalink / raw)
To: Mathias Nyman, Greg Kroah-Hartman
Cc: linux-arm-msm, Bjorn Andersson, Christian Lamparter, linux-usb,
linux-kernel, Yoshihiro Shimoda, Vinod Koul
In-Reply-To: <20190620102154.20805-1-vkoul@kernel.org>
From: Christian Lamparter <chunkeey@googlemail.com>
This patch adds a firmware loader for the uPD720201K8-711-BAC-A
and uPD720202K8-711-BAA-A variant. Both of these chips are listed
in Renesas' R19UH0078EJ0500 Rev.5.00 "User's Manual: Hardware" as
devices which need the firmware loader on page 2 in order to
work as they "do not support the External ROM".
The "Firmware Download Sequence" is describe in chapter
"7.1 FW Download Interface" R19UH0078EJ0500 Rev.5.00 page 131.
The firmware "K2013080.mem" is available from a USB3.0 Host to
PCIe Adapter (PP2U-E card) "Firmware download" archive. An
alternative version can be sourced from Netgear's WNDR4700 GPL
archives.
The release notes of the PP2U-E's "Firmware Download" ver 2.0.1.3
(2012-06-15) state that the firmware is for the following devices:
- uPD720201 ES 2.0 sample whose revision ID is 2.
- uPD720201 ES 2.1 sample & CS sample & Mass product, ID is 3.
- uPD720202 ES 2.0 sample & CS sample & Mass product, ID is 2.
If someone from Renesas is listening: It would be great, if these
firmwares could be added to linux-firmware.git.
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/usb/host/xhci-pci.c | 480 ++++++++++++++++++++++++++++++++++++
1 file changed, 480 insertions(+)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index c2fe218e051f..a400cf7b39da 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -12,6 +12,8 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/acpi.h>
+#include <linux/firmware.h>
+#include <asm/unaligned.h>
#include "xhci.h"
#include "xhci-trace.h"
@@ -279,6 +281,458 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
#endif /* CONFIG_ACPI */
+static const struct renesas_fw_entry {
+ const char *firmware_name;
+ u16 device;
+ u8 revision;
+ u16 expected_version;
+} renesas_fw_table[] = {
+ /*
+ * Only the uPD720201K8-711-BAC-A or uPD720202K8-711-BAA-A
+ * are listed in R19UH0078EJ0500 Rev.5.00 as devices which
+ * need the software loader.
+ *
+ * PP2U/ReleaseNote_USB3-201-202-FW.txt:
+ *
+ * Note: This firmware is for the following devices.
+ * - uPD720201 ES 2.0 sample whose revision ID is 2.
+ * - uPD720201 ES 2.1 sample & CS sample & Mass product, ID is 3.
+ * - uPD720202 ES 2.0 sample & CS sample & Mass product, ID is 2.
+ */
+ { "K2013080.mem", 0x0014, 0x02, 0x2013 },
+ { "K2013080.mem", 0x0014, 0x03, 0x2013 },
+ { "K2013080.mem", 0x0015, 0x02, 0x2013 },
+};
+
+static const struct renesas_fw_entry *renesas_needs_fw_dl(struct pci_dev *dev)
+{
+ const struct renesas_fw_entry *entry;
+ size_t i;
+
+ /* This loader will only work with a RENESAS device. */
+ if (!(dev->vendor == PCI_VENDOR_ID_RENESAS))
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(renesas_fw_table); i++) {
+ entry = &renesas_fw_table[i];
+ if (entry->device == dev->device &&
+ entry->revision == dev->revision)
+ return entry;
+ }
+
+ return NULL;
+}
+
+static int renesas_fw_download_image(struct pci_dev *dev,
+ const u32 *fw,
+ size_t step)
+{
+ size_t i;
+ int err;
+ u8 fw_status;
+ bool data0_or_data1;
+
+ /*
+ * The hardware does alternate between two 32-bit pages.
+ * (This is because each row of the firmware is 8 bytes).
+ *
+ * for even steps we use DATA0, for odd steps DATA1.
+ */
+ data0_or_data1 = (step & 1) == 1;
+
+ /* step+1. Read "Set DATAX" and confirm it is cleared. */
+ for (i = 0; i < 10000; i++) {
+ err = pci_read_config_byte(dev, 0xF5, &fw_status);
+ if (err)
+ return pcibios_err_to_errno(err);
+ if (!(fw_status & BIT(data0_or_data1)))
+ break;
+
+ udelay(1);
+ }
+ if (i == 10000)
+ return -ETIMEDOUT;
+
+ /*
+ * step+2. Write FW data to "DATAX".
+ * "LSB is left" => force little endian
+ */
+ err = pci_write_config_dword(dev, data0_or_data1 ? 0xFC : 0xF8,
+ (__force u32) cpu_to_le32(fw[step]));
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ udelay(100);
+
+ /* step+3. Set "Set DATAX". */
+ err = pci_write_config_byte(dev, 0xF5, BIT(data0_or_data1));
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ return 0;
+}
+
+static int renesas_fw_verify(struct pci_dev *dev,
+ const void *fw_data,
+ size_t length)
+{
+ const struct renesas_fw_entry *entry = renesas_needs_fw_dl(dev);
+ u16 fw_version_pointer;
+ u16 fw_version;
+
+ if (!entry)
+ return -EINVAL;
+
+ /*
+ * The Firmware's Data Format is describe in
+ * "6.3 Data Format" R19UH0078EJ0500 Rev.5.00 page 124
+ */
+
+ /* "Each row is 8 bytes". => firmware size must be a multiple of 8. */
+ if (length % 8 != 0) {
+ dev_err(&dev->dev, "firmware size is not a multipe of 8.");
+ return -EINVAL;
+ }
+
+ /*
+ * The bootrom chips of the big brother have sizes up to 64k, let's
+ * assume that's the biggest the firmware can get.
+ */
+ if (length < 0x1000 || length >= 0x10000) {
+ dev_err(&dev->dev, "firmware is size %zd is not (4k - 64k).",
+ length);
+ return -EINVAL;
+ }
+
+ /* The First 2 bytes are fixed value (55aa). "LSB on Left" */
+ if (get_unaligned_le16(fw_data) != 0x55aa) {
+ dev_err(&dev->dev, "no valid firmware header found.");
+ return -EINVAL;
+ }
+
+ /* verify the firmware version position and print it. */
+ fw_version_pointer = get_unaligned_le16(fw_data + 4);
+ if (fw_version_pointer + 2 >= length) {
+ dev_err(&dev->dev, "firmware version pointer is outside of the firmware image.");
+ return -EINVAL;
+ }
+
+ fw_version = get_unaligned_le16(fw_data + fw_version_pointer);
+ dev_dbg(&dev->dev, "got firmware version: %02x.", fw_version);
+
+ if (fw_version != entry->expected_version) {
+ dev_err(&dev->dev, "firmware version mismatch, expected version: %02x.",
+ entry->expected_version);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int renesas_fw_check_running(struct pci_dev *pdev)
+{
+ int err;
+ u8 fw_state;
+
+ /*
+ * Test if the device is actually needing the firmware. As most
+ * BIOSes will initialize the device for us. If the device is
+ * initialized.
+ */
+ err = pci_read_config_byte(pdev, 0xF4, &fw_state);
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ /*
+ * Check if "FW Download Lock" is locked. If it is and the FW is
+ * ready we can simply continue. If the FW is not ready, we have
+ * to give up.
+ */
+ if (fw_state & BIT(1)) {
+ dev_dbg(&pdev->dev, "FW Download Lock is engaged.");
+
+ if (fw_state & BIT(4))
+ return 0;
+
+ dev_err(&pdev->dev, "FW Download Lock is set and FW is not ready. Giving Up.");
+ return -EIO;
+ }
+
+ /*
+ * Check if "FW Download Enable" is set. If someone (us?) tampered
+ * with it and it can't be resetted, we have to give up too... and
+ * ask for a forgiveness and a reboot.
+ */
+ if (fw_state & BIT(0)) {
+ dev_err(&pdev->dev, "FW Download Enable is stale. Giving Up (poweroff/reboot needed).");
+ return -EIO;
+ }
+
+ /* Otherwise, Check the "Result Code" Bits (6:4) and act accordingly */
+ switch ((fw_state & 0x70)) {
+ case 0: /* No result yet */
+ dev_dbg(&pdev->dev, "FW is not ready/loaded yet.");
+
+ /* tell the caller, that this device needs the firmware. */
+ return 1;
+
+ case BIT(4): /* Success, device should be working. */
+ dev_dbg(&pdev->dev, "FW is ready.");
+ return 0;
+
+ case BIT(5): /* Error State */
+ dev_err(&pdev->dev, "hardware is in an error state. Giving up (poweroff/reboot needed).");
+ return -ENODEV;
+
+ default: /* All other states are marked as "Reserved states" */
+ dev_err(&pdev->dev, "hardware is in an invalid state %x. Giving up (poweroff/reboot needed).",
+ (fw_state & 0x70) >> 4);
+ return -EINVAL;
+ }
+}
+
+static int renesas_hw_check_run_stop_busy(struct pci_dev *pdev)
+{
+#if 0
+ u32 val;
+
+ /*
+ * 7.1.3 Note 3: "... must not set 'FW Download Enable' when
+ * 'RUN/STOP' of USBCMD Register is set"
+ */
+ val = readl(hcd->regs + 0x20);
+ if (val & BIT(0)) {
+ dev_err(&pdev->dev, "hardware is busy and can't receive a FW.");
+ return -EBUSY;
+ }
+#endif
+ return 0;
+}
+
+static int renesas_fw_download(struct pci_dev *pdev,
+ const struct firmware *fw, unsigned int retry_counter)
+{
+ const u32 *fw_data = (const u32 *) fw->data;
+ size_t i;
+ int err;
+ u8 fw_status;
+
+ /*
+ * For more information and the big picture: please look at the
+ * "Firmware Download Sequence" in "7.1 FW Download Interface"
+ * of R19UH0078EJ0500 Rev.5.00 page 131
+ */
+ err = renesas_hw_check_run_stop_busy(pdev);
+ if (err)
+ return err;
+
+ /*
+ * 0. Set "FW Download Enable" bit in the
+ * "FW Download Control & Status Register" at 0xF4
+ */
+ err = pci_write_config_byte(pdev, 0xF4, BIT(0));
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ /* 1 - 10 follow one step after the other. */
+ for (i = 0; i < fw->size / 4; i++) {
+ err = renesas_fw_download_image(pdev, fw_data, i);
+ if (err) {
+ dev_err(&pdev->dev, "Firmware Download Step %zd failed at position %zd bytes with (%d).",
+ i, i * 4, err);
+ return err;
+ }
+ }
+
+ /*
+ * This sequence continues until the last data is written to
+ * "DATA0" or "DATA1". Naturally, we wait until "SET DATA0/1"
+ * is cleared by the hardware beforehand.
+ */
+ for (i = 0; i < 10000; i++) {
+ err = pci_read_config_byte(pdev, 0xF5, &fw_status);
+ if (err)
+ return pcibios_err_to_errno(err);
+ if (!(fw_status & (BIT(0) | BIT(1))))
+ break;
+
+ udelay(1);
+ }
+ if (i == 10000)
+ dev_warn(&pdev->dev, "Final Firmware Download step timed out.");
+
+ /*
+ * 11. After finishing writing the last data of FW, the
+ * System Software must clear "FW Download Enable"
+ */
+ err = pci_write_config_byte(pdev, 0xF4, 0);
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ /* 12. Read "Result Code" and confirm it is good. */
+ for (i = 0; i < 10000; i++) {
+ err = pci_read_config_byte(pdev, 0xF4, &fw_status);
+ if (err)
+ return pcibios_err_to_errno(err);
+ if (fw_status & BIT(4))
+ break;
+
+ udelay(1);
+ }
+ if (i == 10000) {
+ /* Timed out / Error - let's see if we can fix this */
+ err = renesas_fw_check_running(pdev);
+ switch (err) {
+ case 0: /*
+ * we shouldn't end up here.
+ * maybe it took a little bit longer.
+ * But all should be well?
+ */
+ break;
+
+ case 1: /* (No result yet? - we can try to retry) */
+ if (retry_counter < 10) {
+ retry_counter++;
+ dev_warn(&pdev->dev, "Retry Firmware download: %d try.",
+ retry_counter);
+ return renesas_fw_download(pdev, fw,
+ retry_counter);
+ }
+ return -ETIMEDOUT;
+
+ default:
+ return err;
+ }
+ }
+ /*
+ * Optional last step: Engage Firmware Lock
+ *
+ * err = pci_write_config_byte(pdev, 0xF4, BIT(2));
+ * if (err)
+ * return pcibios_err_to_errno(err);
+ */
+
+ return 0;
+}
+
+struct renesas_fw_ctx {
+ struct pci_dev *pdev;
+ const struct pci_device_id *id;
+ bool resume;
+};
+
+static int xhci_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id);
+
+static void renesas_fw_callback(const struct firmware *fw,
+ void *context)
+{
+ struct renesas_fw_ctx *ctx = context;
+ struct pci_dev *pdev = ctx->pdev;
+ struct device *parent = pdev->dev.parent;
+ int err = -ENOENT;
+
+ if (fw) {
+ err = renesas_fw_verify(pdev, fw->data, fw->size);
+ if (!err) {
+ err = renesas_fw_download(pdev, fw, 0);
+ release_firmware(fw);
+ if (!err) {
+ if (ctx->resume)
+ return;
+
+ err = xhci_pci_probe(pdev, ctx->id);
+ if (!err) {
+ /* everything worked */
+ devm_kfree(&pdev->dev, ctx);
+ return;
+ }
+
+ /* in case of an error - fall through */
+ } else {
+ dev_err(&pdev->dev, "firmware failed to download (%d).",
+ err);
+ }
+ }
+ } else {
+ dev_err(&pdev->dev, "firmware failed to load (%d).", err);
+ }
+
+ dev_info(&pdev->dev, "Unloading driver");
+
+ if (parent)
+ device_lock(parent);
+
+ device_release_driver(&pdev->dev);
+
+ if (parent)
+ device_unlock(parent);
+
+ pci_dev_put(pdev);
+}
+
+static int renesas_fw_alive_check(struct pci_dev *pdev)
+{
+ const struct renesas_fw_entry *entry;
+ int err;
+
+ /* check if we have a eligible RENESAS' uPD720201/2 w/o FW. */
+ entry = renesas_needs_fw_dl(pdev);
+ if (!entry)
+ return 0;
+
+ err = renesas_fw_check_running(pdev);
+ /* Also go ahead, if the firmware is running */
+ if (err == 0)
+ return 0;
+
+ /* At this point, we can be sure that the FW isn't ready. */
+ return err;
+}
+
+static int renesas_fw_download_to_hw(struct pci_dev *pdev,
+ const struct pci_device_id *id,
+ bool do_resume)
+{
+ const struct renesas_fw_entry *entry;
+ struct renesas_fw_ctx *ctx;
+ int err;
+
+ /* check if we have a eligible RENESAS' uPD720201/2 w/o FW. */
+ entry = renesas_needs_fw_dl(pdev);
+ if (!entry)
+ return 0;
+
+ err = renesas_fw_check_running(pdev);
+ /* Continue ahead, if the firmware is already running. */
+ if (err == 0)
+ return 0;
+
+ if (err != 1)
+ return err;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->pdev = pdev;
+ ctx->resume = do_resume;
+ ctx->id = id;
+
+ pci_dev_get(pdev);
+ err = request_firmware_nowait(THIS_MODULE, 1, entry->firmware_name,
+ &pdev->dev, GFP_KERNEL, ctx, renesas_fw_callback);
+ if (err) {
+ pci_dev_put(pdev);
+ return err;
+ }
+
+ /*
+ * The renesas_fw_callback() callback will continue the probe
+ * process, once it aquires the firmware.
+ */
+ return 1;
+}
+
/* called during probe() after chip reset completes */
static int xhci_pci_setup(struct usb_hcd *hcd)
{
@@ -317,6 +771,22 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
struct hc_driver *driver;
struct usb_hcd *hcd;
+ /*
+ * Check if this device is a RENESAS uPD720201/2 device.
+ * Otherwise, we can continue with xhci_pci_probe as usual.
+ */
+ retval = renesas_fw_download_to_hw(dev, id, false);
+ switch (retval) {
+ case 0:
+ break;
+
+ case 1: /* let it load the firmware and recontinue the probe. */
+ return 0;
+
+ default:
+ return retval;
+ };
+
driver = (struct hc_driver *)id->driver_data;
/* Prevent runtime suspending between USB-2 and USB-3 initialization */
@@ -381,6 +851,16 @@ static void xhci_pci_remove(struct pci_dev *dev)
{
struct xhci_hcd *xhci;
+ if (renesas_fw_alive_check(dev)) {
+ /*
+ * bail out early, if this was a renesas device w/o FW.
+ * Else we might hit the NMI watchdog in xhci_handsake
+ * during xhci_reset as part of the driver's unloading.
+ * which we forced in the renesas_fw_callback().
+ */
+ return;
+ }
+
xhci = hcd_to_xhci(pci_get_drvdata(dev));
xhci->xhc_state |= XHCI_STATE_REMOVING;
--
2.20.1
^ permalink raw reply related
* [PATCH 2/5] usb: xhci: handle uPD720201 and uPD720202 w/o ROM
From: Vinod Koul @ 2019-06-20 10:21 UTC (permalink / raw)
To: Mathias Nyman, Greg Kroah-Hartman
Cc: linux-arm-msm, Bjorn Andersson, Christian Lamparter, linux-usb,
linux-kernel, Yoshihiro Shimoda, Christian Lamparter, Vinod Koul
In-Reply-To: <20190620102154.20805-1-vkoul@kernel.org>
From: Christian Lamparter <chunkeey@googlemail.com>
This patch adds a firmware check for the uPD720201K8-711-BAC-A
and uPD720202K8-711-BAA-A variant. Both of these chips are listed
in Renesas' R19UH0078EJ0500 Rev.5.00 "User's Manual: Hardware" as
devices which need a firmware in order to work as they do not have
support to load the firmware from an external ROM.
Currently, the xhci-pci driver is unable to initialize the hcd in
this case. Instead it will wait for 30 seconds and cause a timeout
in xhci_handshake() and fails.
[ 5.116990] xhci_hcd 0000:45:00.0: new USB bus registered ...
[ 32.335215] xhci_hcd 0000:45:00.0: can't setup: -110
[ 32.340179] xhci_hcd 0000:45:00.0: USB bus 2 deregistered
[ 32.345587] xhci_hcd 0000:45:00.0: init 0000:45:00.0 fail, -110
[ 32.351496] xhci_hcd: probe of 0000:45:00.0 failed with error -110
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/usb/host/xhci-pci.c | 59 +++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index a400cf7b39da..38a56128c1ee 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -733,6 +733,55 @@ static int renesas_fw_download_to_hw(struct pci_dev *pdev,
return 1;
}
+static int renesas_check_if_fw_dl_is_needed(struct pci_dev *pdev)
+{
+ int err;
+ u8 fw_state;
+
+ /*
+ * Only the uPD720201K8-711-BAC-A or uPD720202K8-711-BAA-A
+ * are listed in R19UH0078EJ0500 Rev.5.00 as devices which
+ * need a firmware in order to work.
+ *
+ * - uPD720202 ES 2.0 sample & CS sample & Mass product, ID is 2.
+ * - uPD720201 ES 2.0 sample whose revision ID is 2.
+ * - uPD720201 ES 2.1 sample & CS sample & Mass product, ID is 3.
+ */
+ if (!((pdev->vendor == PCI_VENDOR_ID_RENESAS) &&
+ ((pdev->device == 0x0015 && pdev->revision == 0x02) ||
+ (pdev->device == 0x0014 &&
+ (pdev->revision == 0x02 || pdev->revision == 0x03)))))
+ return 0;
+
+ /*
+ * Test if the firmware was uploaded and is running.
+ * As most BIOSes will initialize the device for us.
+ */
+ err = pci_read_config_byte(pdev, 0xf4, &fw_state);
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ /* Check the "Result Code" Bits (6:4) and act accordingly */
+ switch (fw_state & 0x70) {
+ case 0: /* No result yet */
+ dev_err(&pdev->dev, "FW is not ready/loaded yet.");
+ return -ENODEV;
+
+ case BIT(4): /* Success, device should be working. */
+ dev_dbg(&pdev->dev, "FW is ready.");
+ return 0;
+
+ case BIT(5): /* Error State */
+ dev_err(&pdev->dev, "HW is in an error state.");
+ return -ENODEV;
+
+ default: /* All other states are marked as "Reserved states" */
+ dev_err(&pdev->dev, "HW is in an invalid state (%x).",
+ (fw_state & 0x70) >> 4);
+ return -EINVAL;
+ }
+}
+
/* called during probe() after chip reset completes */
static int xhci_pci_setup(struct usb_hcd *hcd)
{
@@ -787,6 +836,11 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
return retval;
};
+ /* Check if this device is a RENESAS uPD720201/2 device. */
+ retval = renesas_check_if_fw_dl_is_needed(dev);
+ if (retval)
+ return retval;
+
driver = (struct hc_driver *)id->driver_data;
/* Prevent runtime suspending between USB-2 and USB-3 initialization */
@@ -988,6 +1042,11 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
usb_enable_intel_xhci_ports(pdev);
+ /* Check if this device is a RENESAS uPD720201/2 device. */
+ retval = renesas_check_if_fw_dl_is_needed(pdev);
+ if (retval)
+ return retval;
+
if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
xhci_ssic_port_unused_quirk(hcd, false);
--
2.20.1
^ permalink raw reply related
* [PATCH 3/5] usb: xhci: Use register defined and field names
From: Vinod Koul @ 2019-06-20 10:21 UTC (permalink / raw)
To: Mathias Nyman, Greg Kroah-Hartman
Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, linux-usb,
linux-kernel, Yoshihiro Shimoda, Christian Lamparter
In-Reply-To: <20190620102154.20805-1-vkoul@kernel.org>
Instead of using register values and fields lets define them and
use in the driver.
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/usb/host/xhci-pci.c | 68 +++++++++++++++++++++++++------------
1 file changed, 47 insertions(+), 21 deletions(-)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 38a56128c1ee..a9497c6e3568 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -57,6 +57,27 @@
#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
+#define RENESAS_FW_VERSION 0x6C
+#define RENESAS_ROM_CONFIG 0xF0
+#define RENESAS_FW_STATUS 0xF4
+#define RENESAS_FW_STATUS_MSB 0xF5
+#define RENESAS_ROM_STATUS 0xF6
+#define RENESAS_ROM_STATUS_MSB 0xF7
+#define RENESAS_DATA0 0xF8
+#define RENESAS_DATA1 0xFC
+
+#define RENESAS_FW_VERSION_FIELD GENMASK(23, 7)
+#define RENESAS_FW_VERSION_OFFSET 8
+
+#define RENESAS_FW_STATUS_DOWNLOAD_ENABLE BIT(0)
+#define RENESAS_FW_STATUS_LOCK BIT(1)
+#define RENESAS_FW_STATUS_RESULT GENMASK(6, 4)
+ #define RENESAS_FW_STATUS_INVALID 0
+ #define RENESAS_FW_STATUS_SUCCESS BIT(4)
+ #define RENESAS_FW_STATUS_ERROR BIT(5)
+#define RENESAS_FW_STATUS_SET_DATA0 BIT(8)
+#define RENESAS_FW_STATUS_SET_DATA1 BIT(9)
+
static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -342,7 +363,8 @@ static int renesas_fw_download_image(struct pci_dev *dev,
/* step+1. Read "Set DATAX" and confirm it is cleared. */
for (i = 0; i < 10000; i++) {
- err = pci_read_config_byte(dev, 0xF5, &fw_status);
+ err = pci_read_config_byte(dev, RENESAS_FW_STATUS_MSB,
+ &fw_status);
if (err)
return pcibios_err_to_errno(err);
if (!(fw_status & BIT(data0_or_data1)))
@@ -357,7 +379,8 @@ static int renesas_fw_download_image(struct pci_dev *dev,
* step+2. Write FW data to "DATAX".
* "LSB is left" => force little endian
*/
- err = pci_write_config_dword(dev, data0_or_data1 ? 0xFC : 0xF8,
+ err = pci_write_config_dword(dev, data0_or_data1 ?
+ RENESAS_DATA1 : RENESAS_DATA0,
(__force u32) cpu_to_le32(fw[step]));
if (err)
return pcibios_err_to_errno(err);
@@ -365,7 +388,8 @@ static int renesas_fw_download_image(struct pci_dev *dev,
udelay(100);
/* step+3. Set "Set DATAX". */
- err = pci_write_config_byte(dev, 0xF5, BIT(data0_or_data1));
+ err = pci_write_config_byte(dev, RENESAS_FW_STATUS_MSB,
+ BIT(data0_or_data1));
if (err)
return pcibios_err_to_errno(err);
@@ -439,7 +463,7 @@ static int renesas_fw_check_running(struct pci_dev *pdev)
* BIOSes will initialize the device for us. If the device is
* initialized.
*/
- err = pci_read_config_byte(pdev, 0xF4, &fw_state);
+ err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_state);
if (err)
return pcibios_err_to_errno(err);
@@ -448,10 +472,10 @@ static int renesas_fw_check_running(struct pci_dev *pdev)
* ready we can simply continue. If the FW is not ready, we have
* to give up.
*/
- if (fw_state & BIT(1)) {
+ if (fw_state & RENESAS_FW_STATUS_LOCK) {
dev_dbg(&pdev->dev, "FW Download Lock is engaged.");
- if (fw_state & BIT(4))
+ if (fw_state & RENESAS_FW_STATUS_SUCCESS)
return 0;
dev_err(&pdev->dev, "FW Download Lock is set and FW is not ready. Giving Up.");
@@ -463,30 +487,30 @@ static int renesas_fw_check_running(struct pci_dev *pdev)
* with it and it can't be resetted, we have to give up too... and
* ask for a forgiveness and a reboot.
*/
- if (fw_state & BIT(0)) {
+ if (fw_state & RENESAS_FW_STATUS_DOWNLOAD_ENABLE) {
dev_err(&pdev->dev, "FW Download Enable is stale. Giving Up (poweroff/reboot needed).");
return -EIO;
}
/* Otherwise, Check the "Result Code" Bits (6:4) and act accordingly */
- switch ((fw_state & 0x70)) {
+ switch (fw_state & RENESAS_FW_STATUS_RESULT) {
case 0: /* No result yet */
dev_dbg(&pdev->dev, "FW is not ready/loaded yet.");
/* tell the caller, that this device needs the firmware. */
return 1;
- case BIT(4): /* Success, device should be working. */
+ case RENESAS_FW_STATUS_SUCCESS: /* Success, device should be working. */
dev_dbg(&pdev->dev, "FW is ready.");
return 0;
- case BIT(5): /* Error State */
+ case RENESAS_FW_STATUS_ERROR: /* Error State */
dev_err(&pdev->dev, "hardware is in an error state. Giving up (poweroff/reboot needed).");
return -ENODEV;
default: /* All other states are marked as "Reserved states" */
- dev_err(&pdev->dev, "hardware is in an invalid state %x. Giving up (poweroff/reboot needed).",
- (fw_state & 0x70) >> 4);
+ dev_err(&pdev->dev, "hardware is in an invalid state %lx. Giving up (poweroff/reboot needed).",
+ (fw_state & RENESAS_FW_STATUS_RESULT) >> 4);
return -EINVAL;
}
}
@@ -530,7 +554,8 @@ static int renesas_fw_download(struct pci_dev *pdev,
* 0. Set "FW Download Enable" bit in the
* "FW Download Control & Status Register" at 0xF4
*/
- err = pci_write_config_byte(pdev, 0xF4, BIT(0));
+ err = pci_write_config_byte(pdev, RENESAS_FW_STATUS,
+ RENESAS_FW_STATUS_DOWNLOAD_ENABLE);
if (err)
return pcibios_err_to_errno(err);
@@ -550,7 +575,8 @@ static int renesas_fw_download(struct pci_dev *pdev,
* is cleared by the hardware beforehand.
*/
for (i = 0; i < 10000; i++) {
- err = pci_read_config_byte(pdev, 0xF5, &fw_status);
+ err = pci_read_config_byte(pdev, RENESAS_FW_STATUS_MSB,
+ &fw_status);
if (err)
return pcibios_err_to_errno(err);
if (!(fw_status & (BIT(0) | BIT(1))))
@@ -565,16 +591,16 @@ static int renesas_fw_download(struct pci_dev *pdev,
* 11. After finishing writing the last data of FW, the
* System Software must clear "FW Download Enable"
*/
- err = pci_write_config_byte(pdev, 0xF4, 0);
+ err = pci_write_config_byte(pdev, RENESAS_FW_STATUS, 0);
if (err)
return pcibios_err_to_errno(err);
/* 12. Read "Result Code" and confirm it is good. */
for (i = 0; i < 10000; i++) {
- err = pci_read_config_byte(pdev, 0xF4, &fw_status);
+ err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_status);
if (err)
return pcibios_err_to_errno(err);
- if (fw_status & BIT(4))
+ if (fw_status & RENESAS_FW_STATUS_SUCCESS)
break;
udelay(1);
@@ -757,21 +783,21 @@ static int renesas_check_if_fw_dl_is_needed(struct pci_dev *pdev)
* Test if the firmware was uploaded and is running.
* As most BIOSes will initialize the device for us.
*/
- err = pci_read_config_byte(pdev, 0xf4, &fw_state);
+ err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_state);
if (err)
return pcibios_err_to_errno(err);
/* Check the "Result Code" Bits (6:4) and act accordingly */
- switch (fw_state & 0x70) {
+ switch (fw_state & RENESAS_FW_STATUS_RESULT) {
case 0: /* No result yet */
dev_err(&pdev->dev, "FW is not ready/loaded yet.");
return -ENODEV;
- case BIT(4): /* Success, device should be working. */
+ case RENESAS_FW_STATUS_SUCCESS:
dev_dbg(&pdev->dev, "FW is ready.");
return 0;
- case BIT(5): /* Error State */
+ case RENESAS_FW_STATUS_ERROR:
dev_err(&pdev->dev, "HW is in an error state.");
return -ENODEV;
--
2.20.1
^ permalink raw reply related
* [PATCH 4/5] usb: xhci: Add ROM loader for uPD720201
From: Vinod Koul @ 2019-06-20 10:21 UTC (permalink / raw)
To: Mathias Nyman, Greg Kroah-Hartman
Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, linux-usb,
linux-kernel, Yoshihiro Shimoda, Christian Lamparter
In-Reply-To: <20190620102154.20805-1-vkoul@kernel.org>
uPD720201 supports ROM and allows software to program the ROM and boot
from it. Add support for detecting if ROM is present, if so load the ROM
if not programmed earlier.
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/usb/host/xhci-pci.c | 358 ++++++++++++++++++++++++++++++++++++
1 file changed, 358 insertions(+)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index a9497c6e3568..3574afac44c5 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -78,6 +78,20 @@
#define RENESAS_FW_STATUS_SET_DATA0 BIT(8)
#define RENESAS_FW_STATUS_SET_DATA1 BIT(9)
+#define RENESAS_ROM_STATUS_ACCESS BIT(0)
+#define RENESAS_ROM_STATUS_ERASE BIT(1)
+#define RENESAS_ROM_STATUS_RELOAD BIT(2)
+#define RENESAS_ROM_STATUS_RESULT GENMASK(6, 4)
+ #define RENESAS_ROM_STATUS_INVALID 0
+ #define RENESAS_ROM_STATUS_SUCCESS BIT(4)
+ #define RENESAS_ROM_STATUS_ERROR BIT(5)
+#define RENESAS_ROM_STATUS_SET_DATA0 BIT(8)
+#define RENESAS_ROM_STATUS_SET_DATA1 BIT(9)
+#define RENESAS_ROM_STATUS_ROM_EXISTS BIT(15)
+
+#define RENESAS_ROM_ERASE_MAGIC 0x5A65726F
+#define RENESAS_ROM_WRITE_MAGIC 0x53524F4D
+
static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -453,11 +467,75 @@ static int renesas_fw_verify(struct pci_dev *dev,
return 0;
}
+static int renesas_check_rom_state(struct pci_dev *pdev)
+{
+ const struct renesas_fw_entry *entry;
+ u16 rom_state;
+ u32 version;
+ bool valid_version = false;
+ int err, i;
+
+ /* check FW version */
+ err = pci_read_config_dword(pdev, RENESAS_FW_VERSION, &version);
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ version &= RENESAS_FW_VERSION_FIELD;
+ version = version >> RENESAS_FW_VERSION_OFFSET;
+ dev_dbg(&pdev->dev, "Found FW version loaded is %x\n", version);
+
+ /* treat version in renesas_fw_table as correct ones */
+ for (i = 0; i < ARRAY_SIZE(renesas_fw_table); i++) {
+ entry = &renesas_fw_table[i];
+ if (version == entry->expected_version) {
+ dev_dbg(&pdev->dev, "Detected valid ROM version..\n");
+ valid_version = true;
+ }
+ }
+
+ /*
+ * Test if ROM is present and loaded, if so we can skip everything
+ */
+ err = pci_read_config_word(pdev, RENESAS_ROM_STATUS, &rom_state);
+ if (err)
+ return pcibios_err_to_errno(err);
+
+ if (rom_state & BIT(15)) {
+ /* ROM exists */
+ dev_dbg(&pdev->dev, "ROM exists\n");
+
+ /* Check the "Result Code" Bits (6:4) and act accordingly */
+ switch (rom_state & RENESAS_ROM_STATUS_RESULT) {
+ case RENESAS_ROM_STATUS_SUCCESS:
+ dev_dbg(&pdev->dev, "Success ROM load...");
+ /* we have valid version and status so success */
+ if (valid_version)
+ return 0;
+ case RENESAS_ROM_STATUS_INVALID: /* No result yet */
+ dev_dbg(&pdev->dev, "No result as it is ROM...");
+ /* we have valid version and status so success */
+ if (valid_version)
+ return 0;
+ case RENESAS_ROM_STATUS_ERROR: /* Error State */
+ default: /* All other states are marked as "Reserved states" */
+ dev_err(&pdev->dev, "Invalid ROM..");
+ break;
+ }
+ }
+
+ return -EIO;
+}
+
static int renesas_fw_check_running(struct pci_dev *pdev)
{
int err;
u8 fw_state;
+ /* Check if device has ROM and loaded, if so skip everything */
+ err = renesas_check_rom_state(pdev);
+ if (!err)
+ return err;
+
/*
* Test if the device is actually needing the firmware. As most
* BIOSes will initialize the device for us. If the device is
@@ -650,17 +728,292 @@ struct renesas_fw_ctx {
static int xhci_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
+static bool renesas_check_rom(struct pci_dev *pdev)
+{
+ u16 rom_status;
+ int retval;
+
+ /* 1. Check if external ROM exists */
+ retval = pci_read_config_word(pdev, RENESAS_ROM_STATUS, &rom_status);
+ if (retval)
+ return false;
+
+ rom_status &= RENESAS_ROM_STATUS_ROM_EXISTS;
+ if (rom_status) {
+ dev_dbg(&pdev->dev, "External ROM exists\n");
+ return true; /* External ROM exists */
+ }
+
+ return false;
+}
+
+static void renesas_rom_erase(struct pci_dev *pdev)
+{
+ int retval, i;
+ u8 status;
+
+ dev_dbg(&pdev->dev, "Performing ROM Erase...\n");
+ retval = pci_write_config_dword(pdev, RENESAS_DATA0,
+ RENESAS_ROM_ERASE_MAGIC);
+ if (retval) {
+ dev_err(&pdev->dev, "ROM erase, magic word write failed: %d\n",
+ pcibios_err_to_errno(retval));
+ return;
+ }
+
+ retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
+ if (retval) {
+ dev_err(&pdev->dev, "ROM status read failed: %d\n",
+ pcibios_err_to_errno(retval));
+ return;
+ }
+ status |= RENESAS_ROM_STATUS_ERASE;
+ retval = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, status);
+ if (retval) {
+ dev_err(&pdev->dev, "ROM erase set word write failed\n");
+ return;
+ }
+
+ /* sleep a bit while ROM is erased */
+ msleep(20);
+
+ for (i = 0; i < 10000; i++) {
+ retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS,
+ &status);
+ status &= RENESAS_ROM_STATUS_ERASE;
+ if (!status)
+ break;
+
+ mdelay(10);
+ }
+
+ if (i == 10000)
+ dev_dbg(&pdev->dev, "Chip erase timedout: %x\n", status);
+
+ dev_dbg(&pdev->dev, "ROM Erase... Done success\n");
+}
+
+static bool renesas_download_rom(struct pci_dev *pdev,
+ const u32 *fw, size_t step)
+{
+ bool data0_or_data1;
+ u8 fw_status;
+ size_t i;
+ int err;
+
+ /*
+ * The hardware does alternate between two 32-bit pages.
+ * (This is because each row of the firmware is 8 bytes).
+ *
+ * for even steps we use DATA0, for odd steps DATA1.
+ */
+ data0_or_data1 = (step & 1) == 1;
+
+ /* Read "Set DATAX" and confirm it is cleared. */
+ for (i = 0; i < 10000; i++) {
+ err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS_MSB,
+ &fw_status);
+ if (err) {
+ dev_err(&pdev->dev, "Read ROM Status failed: %d\n",
+ pcibios_err_to_errno(err));
+ return false;
+ }
+ if (!(fw_status & BIT(data0_or_data1)))
+ break;
+
+ udelay(100);
+ }
+ if (i == 10000) {
+ dev_err(&pdev->dev, "Timeout for Set DATAX step: %zd\n", step);
+ return false;
+ }
+
+ /*
+ * Write FW data to "DATAX".
+ * "LSB is left" => force little endian
+ */
+ err = pci_write_config_dword(pdev, data0_or_data1 ?
+ RENESAS_DATA1 : RENESAS_DATA0,
+ (__force u32)cpu_to_le32(fw[step]));
+ if (err) {
+ dev_err(&pdev->dev, "Write to DATAX failed: %d\n",
+ pcibios_err_to_errno(err));
+ return false;
+ }
+
+ udelay(100);
+
+ /* Set "Set DATAX". */
+ err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS_MSB,
+ BIT(data0_or_data1));
+ if (err) {
+ dev_err(&pdev->dev, "Write config for DATAX failed: %d\n",
+ pcibios_err_to_errno(err));
+ return false;
+ }
+
+ return true;
+}
+
+static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
+{
+ const u32 *fw_data = (const u32 *)fw->data;
+ int err, i;
+ u8 status;
+
+ /* 2. Write magic word to Data0 */
+ err = pci_write_config_dword(pdev, RENESAS_DATA0,
+ RENESAS_ROM_WRITE_MAGIC);
+ if (err)
+ return false;
+
+ /* 3. Set External ROM access */
+ err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS,
+ RENESAS_ROM_STATUS_ACCESS);
+ if (err)
+ goto remove_bypass;
+
+ /* 4. Check the result */
+ err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
+ if (err)
+ goto remove_bypass;
+ status &= GENMASK(6, 4);
+ if (status) {
+ dev_err(&pdev->dev,
+ "setting external rom failed: %x\n", status);
+ goto remove_bypass;
+ }
+
+ /* 5 to 16 Write FW to DATA0/1 while checking SetData0/1 */
+ for (i = 0; i < fw->size / 4; i++) {
+ err = renesas_download_rom(pdev, fw_data, i);
+ if (!err) {
+ dev_err(&pdev->dev,
+ "ROM Download Step %d failed at position %d bytes\n",
+ i, i * 4);
+ goto remove_bypass;
+ }
+ }
+
+ /*
+ * wait till DATA0/1 is cleared
+ */
+ for (i = 0; i < 1000; i++) {
+ err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS_MSB,
+ &status);
+ if (err)
+ goto remove_bypass;
+ if (!(status & (BIT(0) | BIT(1))))
+ break;
+
+ udelay(10);
+ }
+ if (i == 1000) {
+ dev_err(&pdev->dev, "Final Firmware ROM Download step timed out\n");
+ goto remove_bypass;
+ }
+
+ /* 17. Remove bypass */
+ err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, 0);
+ if (err)
+ return false;
+
+ udelay(10);
+
+ /* 18. check result */
+ for (i = 0; i < 10000; i++) {
+ err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
+ if (err) {
+ dev_err(&pdev->dev, "Read ROM status failed:%d\n",
+ pcibios_err_to_errno(err));
+ return false;
+ }
+ status &= RENESAS_ROM_STATUS_RESULT;
+ if (status == RENESAS_ROM_STATUS_SUCCESS) {
+ dev_dbg(&pdev->dev, "Download ROM success\n");
+ break;
+ }
+ udelay(100);
+ }
+ if (i == 10000) { /* Timed out */
+ dev_err(&pdev->dev,
+ "Download to external ROM TO: %x\n", status);
+ return false;
+ }
+
+ dev_dbg(&pdev->dev, "Download to external ROM scuceeded\n");
+
+ /* Last step set Reload */
+ err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS,
+ RENESAS_ROM_STATUS_RELOAD);
+ if (err) {
+ dev_err(&pdev->dev, "Set ROM execute failed: %d\n",
+ pcibios_err_to_errno(err));
+ return false;
+ }
+
+ /*
+ * wait till Reload is cleared
+ */
+ for (i = 0; i < 10000; i++) {
+ err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
+ if (err)
+ return false;
+ if (!(status & RENESAS_ROM_STATUS_RELOAD))
+ break;
+
+ udelay(1);
+ }
+ if (i == 10000) {
+ dev_err(&pdev->dev, "ROM Exec timed out: %x\n", status);
+ return false;
+ }
+
+ return true;
+
+remove_bypass:
+ pci_write_config_byte(pdev, RENESAS_ROM_STATUS, 0);
+ return false;
+}
+
static void renesas_fw_callback(const struct firmware *fw,
void *context)
{
struct renesas_fw_ctx *ctx = context;
struct pci_dev *pdev = ctx->pdev;
struct device *parent = pdev->dev.parent;
+ bool rom;
int err = -ENOENT;
if (fw) {
err = renesas_fw_verify(pdev, fw->data, fw->size);
if (!err) {
+ /* Check if the device has external ROM */
+ rom = renesas_check_rom(pdev);
+ if (rom) {
+ /* perfrom chip erase first */
+ renesas_rom_erase(pdev);
+
+ /* lets try loading fw on ROM first */
+ rom = renesas_setup_rom(pdev, fw);
+ if (!rom) {
+ dev_err(&pdev->dev, "ROM load failed, falling back on FW load\n");
+ } else {
+ dev_dbg(&pdev->dev, "ROM load done..\n");
+
+ release_firmware(fw);
+ if (ctx->resume)
+ return;
+
+ err = xhci_pci_probe(pdev, ctx->id);
+ if (!err) {
+ /* everything worked */
+ devm_kfree(&pdev->dev, ctx);
+ return;
+ }
+ }
+ }
+
err = renesas_fw_download(pdev, fw, 0);
release_firmware(fw);
if (!err) {
@@ -779,6 +1132,11 @@ static int renesas_check_if_fw_dl_is_needed(struct pci_dev *pdev)
(pdev->revision == 0x02 || pdev->revision == 0x03)))))
return 0;
+ /* Check if device has ROM and loaded, if so skip everything */
+ err = renesas_check_rom_state(pdev);
+ if (!err)
+ return err;
+
/*
* Test if the firmware was uploaded and is running.
* As most BIOSes will initialize the device for us.
--
2.20.1
^ permalink raw reply related
* [PATCH 5/5] usb: xhci: allow multiple firmware versions
From: Vinod Koul @ 2019-06-20 10:21 UTC (permalink / raw)
To: Mathias Nyman, Greg Kroah-Hartman
Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, linux-usb,
linux-kernel, Yoshihiro Shimoda, Christian Lamparter
In-Reply-To: <20190620102154.20805-1-vkoul@kernel.org>
Allow multiple firmware file versions in table and load them in
increasing order as we find them in the file system.
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: Christian Lamparter <chunkeey@googlemail.com>
---
drivers/usb/host/xhci-pci.c | 39 +++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 3574afac44c5..2ee9e6bbabcb 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -333,9 +333,12 @@ static const struct renesas_fw_entry {
* - uPD720201 ES 2.0 sample whose revision ID is 2.
* - uPD720201 ES 2.1 sample & CS sample & Mass product, ID is 3.
* - uPD720202 ES 2.0 sample & CS sample & Mass product, ID is 2.
+ *
+ * Entry expected_version should be kept in increasing order
*/
{ "K2013080.mem", 0x0014, 0x02, 0x2013 },
{ "K2013080.mem", 0x0014, 0x03, 0x2013 },
+ { "K2026090.mem", 0x0014, 0x03, 0x2026 },
{ "K2013080.mem", 0x0015, 0x02, 0x2013 },
};
@@ -358,6 +361,24 @@ static const struct renesas_fw_entry *renesas_needs_fw_dl(struct pci_dev *dev)
return NULL;
}
+static const struct
+renesas_fw_entry *renesas_get_next_entry(struct pci_dev *dev,
+ const struct renesas_fw_entry *entry)
+{
+ const struct renesas_fw_entry *next_entry;
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(renesas_fw_table); i++) {
+ next_entry = &renesas_fw_table[i];
+ if (next_entry->device == dev->device &&
+ next_entry->revision == dev->revision &&
+ next_entry->expected_version > entry->expected_version)
+ return next_entry;
+ }
+
+ return NULL;
+}
+
static int renesas_fw_download_image(struct pci_dev *dev,
const u32 *fw,
size_t step)
@@ -723,6 +744,7 @@ struct renesas_fw_ctx {
struct pci_dev *pdev;
const struct pci_device_id *id;
bool resume;
+ const struct renesas_fw_entry *entry;
};
static int xhci_pci_probe(struct pci_dev *pdev,
@@ -982,6 +1004,7 @@ static void renesas_fw_callback(const struct firmware *fw,
struct renesas_fw_ctx *ctx = context;
struct pci_dev *pdev = ctx->pdev;
struct device *parent = pdev->dev.parent;
+ const struct renesas_fw_entry *next_entry;
bool rom;
int err = -ENOENT;
@@ -1035,6 +1058,21 @@ static void renesas_fw_callback(const struct firmware *fw,
}
} else {
dev_err(&pdev->dev, "firmware failed to load (%d).", err);
+ /*
+ * we didn't find firmware, check if we have another
+ * entry for this device
+ */
+ next_entry = renesas_get_next_entry(ctx->pdev, ctx->entry);
+ if (next_entry) {
+ ctx->entry = next_entry;
+ dev_dbg(&pdev->dev, "Found next entry, requesting: %s\n",
+ next_entry->firmware_name);
+ request_firmware_nowait(THIS_MODULE, 1,
+ next_entry->firmware_name,
+ &pdev->dev, GFP_KERNEL,
+ ctx, renesas_fw_callback);
+ return;
+ }
}
dev_info(&pdev->dev, "Unloading driver");
@@ -1096,6 +1134,7 @@ static int renesas_fw_download_to_hw(struct pci_dev *pdev,
ctx->pdev = pdev;
ctx->resume = do_resume;
ctx->id = id;
+ ctx->entry = entry;
pci_dev_get(pdev);
err = request_firmware_nowait(THIS_MODULE, 1, entry->firmware_name,
--
2.20.1
^ permalink raw reply related
* [PATCH 0/5] usb: xhci: Add support for Renesas USB controllers
From: Vinod Koul @ 2019-06-20 10:21 UTC (permalink / raw)
To: Mathias Nyman, Greg Kroah-Hartman
Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Yoshihiro Shimoda,
Christian Lamparter, linux-usb, linux-kernel
This series add support for Renesas USB controllers uPD720201 and uPD720202.
These require firmware to be loaded and in case devices have ROM those can
also be programmed if empty. If ROM is porgrammed, it runs from ROM as well.
This includes two patches from Christian which supported these controllers
w/o ROM and later my patches for ROM support and multiple firmware versions.
Christian Lamparter (2):
usb: xhci: add firmware loader for uPD720201 and uPD720202 w/o ROM
usb: xhci: handle uPD720201 and uPD720202 w/o ROM
Vinod Koul (3):
usb: xhci: Use register defined and field names
usb: xhci: Add ROM loader for uPD720201
usb: xhci: allow multiple firmware versions
drivers/usb/host/xhci-pci.c | 962 ++++++++++++++++++++++++++++++++++++
1 file changed, 962 insertions(+)
--
2.20.1
^ permalink raw reply
* [PATCH] drm/i915/selftests: Use request managed wakerefs
From: Chris Wilson @ 2019-06-20 10:24 UTC (permalink / raw)
To: intel-gfx
Since commit 79ffac8599c4 ("drm/i915: Invert the GEM wakeref
hierarchy"), the request creation itself took responsibility for
managing the engine/GT wakerefs and so we can remove the redundant grabs
in our selftests.
References: 79ffac8599c4 ("drm/i915: Invert the GEM wakeref hierarchy")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
.../drm/i915/gem/selftests/i915_gem_context.c | 35 ++++---------------
1 file changed, 7 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index eaa2b16574c7..f2d4e773404a 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -31,7 +31,6 @@ static int live_nop_switch(void *arg)
struct intel_engine_cs *engine;
struct i915_gem_context **ctx;
enum intel_engine_id id;
- intel_wakeref_t wakeref;
struct igt_live_test t;
struct drm_file *file;
unsigned long n;
@@ -53,7 +52,6 @@ static int live_nop_switch(void *arg)
return PTR_ERR(file);
mutex_lock(&i915->drm.struct_mutex);
- wakeref = intel_runtime_pm_get(&i915->runtime_pm);
ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL);
if (!ctx) {
@@ -152,7 +150,6 @@ static int live_nop_switch(void *arg)
}
out_unlock:
- intel_runtime_pm_put(&i915->runtime_pm, wakeref);
mutex_unlock(&i915->drm.struct_mutex);
mock_file_free(i915, file);
return err;
@@ -507,7 +504,6 @@ static int igt_ctx_exec(void *arg)
dw = 0;
while (!time_after(jiffies, end_time)) {
struct i915_gem_context *ctx;
- intel_wakeref_t wakeref;
ctx = live_context(i915, file);
if (IS_ERR(ctx)) {
@@ -523,8 +519,7 @@ static int igt_ctx_exec(void *arg)
}
}
- with_intel_runtime_pm(&i915->runtime_pm, wakeref)
- err = gpu_fill(obj, ctx, engine, dw);
+ err = gpu_fill(obj, ctx, engine, dw);
if (err) {
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
ndwords, dw, max_dwords(obj),
@@ -623,7 +618,6 @@ static int igt_shared_ctx_exec(void *arg)
ncontexts = 0;
while (!time_after(jiffies, end_time)) {
struct i915_gem_context *ctx;
- intel_wakeref_t wakeref;
ctx = kernel_context(i915);
if (IS_ERR(ctx)) {
@@ -642,9 +636,7 @@ static int igt_shared_ctx_exec(void *arg)
}
}
- err = 0;
- with_intel_runtime_pm(&i915->runtime_pm, wakeref)
- err = gpu_fill(obj, ctx, engine, dw);
+ err = gpu_fill(obj, ctx, engine, dw);
if (err) {
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
ndwords, dw, max_dwords(obj),
@@ -1030,7 +1022,6 @@ __igt_ctx_sseu(struct drm_i915_private *i915,
struct i915_gem_context *ctx;
struct intel_context *ce;
struct intel_sseu pg_sseu;
- intel_wakeref_t wakeref;
struct drm_file *file;
int ret;
@@ -1078,12 +1069,10 @@ __igt_ctx_sseu(struct drm_i915_private *i915,
goto out_unlock;
}
- wakeref = intel_runtime_pm_get(&i915->runtime_pm);
-
ce = i915_gem_context_get_engine(ctx, RCS0);
if (IS_ERR(ce)) {
ret = PTR_ERR(ce);
- goto out_rpm;
+ goto out_put;
}
ret = intel_context_pin(ce);
@@ -1117,8 +1106,7 @@ __igt_ctx_sseu(struct drm_i915_private *i915,
intel_context_unpin(ce);
out_context:
intel_context_put(ce);
-out_rpm:
- intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+out_put:
i915_gem_object_put(obj);
out_unlock:
@@ -1207,8 +1195,6 @@ static int igt_ctx_readonly(void *arg)
unsigned int id;
for_each_engine(engine, i915, id) {
- intel_wakeref_t wakeref;
-
if (!intel_engine_can_store_dword(engine))
continue;
@@ -1223,9 +1209,7 @@ static int igt_ctx_readonly(void *arg)
i915_gem_object_set_readonly(obj);
}
- err = 0;
- with_intel_runtime_pm(&i915->runtime_pm, wakeref)
- err = gpu_fill(obj, ctx, engine, dw);
+ err = gpu_fill(obj, ctx, engine, dw);
if (err) {
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
ndwords, dw, max_dwords(obj),
@@ -1488,7 +1472,6 @@ static int igt_vm_isolation(void *arg)
struct drm_i915_private *i915 = arg;
struct i915_gem_context *ctx_a, *ctx_b;
struct intel_engine_cs *engine;
- intel_wakeref_t wakeref;
struct igt_live_test t;
struct drm_file *file;
I915_RND_STATE(prng);
@@ -1535,8 +1518,6 @@ static int igt_vm_isolation(void *arg)
GEM_BUG_ON(ctx_b->vm->total != vm_total);
vm_total -= I915_GTT_PAGE_SIZE;
- wakeref = intel_runtime_pm_get(&i915->runtime_pm);
-
count = 0;
for_each_engine(engine, i915, id) {
IGT_TIMEOUT(end_time);
@@ -1560,7 +1541,7 @@ static int igt_vm_isolation(void *arg)
err = read_from_scratch(ctx_b, engine,
offset, &value);
if (err)
- goto out_rpm;
+ goto out_unlock;
if (value) {
pr_err("%s: Read %08x from scratch (offset 0x%08x_%08x), after %lu reads!\n",
@@ -1569,7 +1550,7 @@ static int igt_vm_isolation(void *arg)
lower_32_bits(offset),
this);
err = -EINVAL;
- goto out_rpm;
+ goto out_unlock;
}
this++;
@@ -1579,8 +1560,6 @@ static int igt_vm_isolation(void *arg)
pr_info("Checked %lu scratch offsets across %d engines\n",
count, RUNTIME_INFO(i915)->num_engines);
-out_rpm:
- intel_runtime_pm_put(&i915->runtime_pm, wakeref);
out_unlock:
if (igt_live_test_end(&t))
err = -EIO;
--
2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related
* irq-sifive-plic + gpio-sifive break IRQF_ONESHOT
From: Charles Papon @ 2019-06-20 10:24 UTC (permalink / raw)
To: linux-riscv
Hi,
Was using a chip driver (W5500) which use a threaded irq with the
IRQF_TRIGGER_LOW | IRQF_ONESHOT flags and i got some issues.
The interrupt should have been masked to wait the W5500 irq handler to
be executed, but that wasn't the case.
As far my understanding go, the plic driver should use
handle_level_irq instead of handle_simple_irq, as interrupts connected
on it could be level triggerd.
Also, the plic irq_mask/irq_unmask should be implemented for two reasons :
- If they are null, it make crash chained_irq_enter calls from let's
say connected gpio drivers durring IRQ handeling
- the irq_unmask is very much required to handle threaded IRQF_ONESHOT IRQ
So maybe the plic claim release (writel(hwirq, claim);) should be
moved into its irq_unmask, and the irq_mask should be implemented as a
dummy function.
The same kind of issue appeared witht eh gpio-sifive driver, the
driver is using handle_level_irq instead of handle_simple_irq and do
not implement the unmask, which break the IRQF_ONESHOT handeling.
Do you agree ? I'm not experienced in linux dev.
Thanks
Charles
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply
* [Qemu-devel] [PATCH v3 3/4] target/mips: Fix some space checkpatch errors in translate.c
From: Aleksandar Markovic @ 2019-06-20 10:02 UTC (permalink / raw)
To: qemu-devel; +Cc: arikalo, amarkovic
In-Reply-To: <1561024929-26004-1-git-send-email-aleksandar.markovic@rt-rk.com>
From: Aleksandar Markovic <amarkovic@wavecomp.com>
Remove some space-related checkpatch warning.
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
---
target/mips/translate.c | 240 ++++++++++++++++++++++++------------------------
1 file changed, 122 insertions(+), 118 deletions(-)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index a3cf976..54e0160 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -2617,7 +2617,7 @@ static const char * const mxuregnames[] = {
} while (0)
/* General purpose registers moves. */
-static inline void gen_load_gpr (TCGv t, int reg)
+static inline void gen_load_gpr(TCGv t, int reg)
{
if (reg == 0)
tcg_gen_movi_tl(t, 0);
@@ -2625,14 +2625,14 @@ static inline void gen_load_gpr (TCGv t, int reg)
tcg_gen_mov_tl(t, cpu_gpr[reg]);
}
-static inline void gen_store_gpr (TCGv t, int reg)
+static inline void gen_store_gpr(TCGv t, int reg)
{
if (reg != 0)
tcg_gen_mov_tl(cpu_gpr[reg], t);
}
/* Moves to/from shadow registers. */
-static inline void gen_load_srsgpr (int from, int to)
+static inline void gen_load_srsgpr(int from, int to)
{
TCGv t0 = tcg_temp_new();
@@ -2839,7 +2839,7 @@ static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
}
}
-static inline int get_fp_bit (int cc)
+static inline int get_fp_bit(int cc)
{
if (cc)
return 24 + cc;
@@ -2848,7 +2848,8 @@ static inline int get_fp_bit (int cc)
}
/* Addresses computation */
-static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
+static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
+ TCGv arg1)
{
tcg_gen_add_tl(ret, arg0, arg1);
@@ -3328,8 +3329,8 @@ OP_LD_ATOMIC(lld,ld64);
#endif
#undef OP_LD_ATOMIC
-static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
- int base, int offset)
+static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
+ int base, int offset)
{
if (base == 0) {
tcg_gen_movi_tl(addr, offset);
@@ -3341,7 +3342,7 @@ static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
}
}
-static target_ulong pc_relative_pc (DisasContext *ctx)
+static target_ulong pc_relative_pc(DisasContext *ctx)
{
target_ulong pc = ctx->base.pc_next;
@@ -3578,8 +3579,8 @@ static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
}
/* Store */
-static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
- int base, int offset)
+static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
+ int base, int offset)
{
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
@@ -3717,8 +3718,8 @@ static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
}
/* Load and store */
-static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
- TCGv t0)
+static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
+ TCGv t0)
{
/* Don't do NOP if destination is zero: we must perform the actual
memory access. */
@@ -5132,8 +5133,8 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
tcg_temp_free(t1);
}
-static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
- int rd, int rs, int rt)
+static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
{
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
@@ -5196,8 +5197,8 @@ static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
tcg_temp_free(t1);
}
-static void gen_cl (DisasContext *ctx, uint32_t opc,
- int rd, int rs)
+static void gen_cl(DisasContext *ctx, uint32_t opc,
+ int rd, int rs)
{
TCGv t0;
@@ -6188,8 +6189,8 @@ static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
/* special3 bitfield operations */
-static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
- int rs, int lsb, int msb)
+static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
+ int rs, int lsb, int msb)
{
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
@@ -6259,7 +6260,7 @@ fail:
tcg_temp_free(t1);
}
-static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
+static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
{
TCGv t0;
@@ -6502,7 +6503,7 @@ static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
tcg_temp_free_i64(t0);
}
-static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
+static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
{
TCGv_i32 t0 = tcg_temp_new_i32();
@@ -6511,13 +6512,13 @@ static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
tcg_temp_free_i32(t0);
}
-static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
+static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
{
tcg_gen_ld_tl(arg, cpu_env, off);
tcg_gen_ext32s_tl(arg, arg);
}
-static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
+static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
{
TCGv_i32 t0 = tcg_temp_new_i32();
@@ -10077,7 +10078,8 @@ die:
generate_exception_end(ctx, EXCP_RI);
}
-static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
+static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+ int rt, int rd)
{
const char *opn = "ldst";
@@ -10465,22 +10467,22 @@ enum fopcode {
OPC_CVT_W_S = FOP(36, FMT_S),
OPC_CVT_L_S = FOP(37, FMT_S),
OPC_CVT_PS_S = FOP(38, FMT_S),
- OPC_CMP_F_S = FOP (48, FMT_S),
- OPC_CMP_UN_S = FOP (49, FMT_S),
- OPC_CMP_EQ_S = FOP (50, FMT_S),
- OPC_CMP_UEQ_S = FOP (51, FMT_S),
- OPC_CMP_OLT_S = FOP (52, FMT_S),
- OPC_CMP_ULT_S = FOP (53, FMT_S),
- OPC_CMP_OLE_S = FOP (54, FMT_S),
- OPC_CMP_ULE_S = FOP (55, FMT_S),
- OPC_CMP_SF_S = FOP (56, FMT_S),
- OPC_CMP_NGLE_S = FOP (57, FMT_S),
- OPC_CMP_SEQ_S = FOP (58, FMT_S),
- OPC_CMP_NGL_S = FOP (59, FMT_S),
- OPC_CMP_LT_S = FOP (60, FMT_S),
- OPC_CMP_NGE_S = FOP (61, FMT_S),
- OPC_CMP_LE_S = FOP (62, FMT_S),
- OPC_CMP_NGT_S = FOP (63, FMT_S),
+ OPC_CMP_F_S = FOP(48, FMT_S),
+ OPC_CMP_UN_S = FOP(49, FMT_S),
+ OPC_CMP_EQ_S = FOP(50, FMT_S),
+ OPC_CMP_UEQ_S = FOP(51, FMT_S),
+ OPC_CMP_OLT_S = FOP(52, FMT_S),
+ OPC_CMP_ULT_S = FOP(53, FMT_S),
+ OPC_CMP_OLE_S = FOP(54, FMT_S),
+ OPC_CMP_ULE_S = FOP(55, FMT_S),
+ OPC_CMP_SF_S = FOP(56, FMT_S),
+ OPC_CMP_NGLE_S = FOP(57, FMT_S),
+ OPC_CMP_SEQ_S = FOP(58, FMT_S),
+ OPC_CMP_NGL_S = FOP(59, FMT_S),
+ OPC_CMP_LT_S = FOP(60, FMT_S),
+ OPC_CMP_NGE_S = FOP(61, FMT_S),
+ OPC_CMP_LE_S = FOP(62, FMT_S),
+ OPC_CMP_NGT_S = FOP(63, FMT_S),
OPC_ADD_D = FOP(0, FMT_D),
OPC_SUB_D = FOP(1, FMT_D),
@@ -10521,22 +10523,22 @@ enum fopcode {
OPC_CVT_S_D = FOP(32, FMT_D),
OPC_CVT_W_D = FOP(36, FMT_D),
OPC_CVT_L_D = FOP(37, FMT_D),
- OPC_CMP_F_D = FOP (48, FMT_D),
- OPC_CMP_UN_D = FOP (49, FMT_D),
- OPC_CMP_EQ_D = FOP (50, FMT_D),
- OPC_CMP_UEQ_D = FOP (51, FMT_D),
- OPC_CMP_OLT_D = FOP (52, FMT_D),
- OPC_CMP_ULT_D = FOP (53, FMT_D),
- OPC_CMP_OLE_D = FOP (54, FMT_D),
- OPC_CMP_ULE_D = FOP (55, FMT_D),
- OPC_CMP_SF_D = FOP (56, FMT_D),
- OPC_CMP_NGLE_D = FOP (57, FMT_D),
- OPC_CMP_SEQ_D = FOP (58, FMT_D),
- OPC_CMP_NGL_D = FOP (59, FMT_D),
- OPC_CMP_LT_D = FOP (60, FMT_D),
- OPC_CMP_NGE_D = FOP (61, FMT_D),
- OPC_CMP_LE_D = FOP (62, FMT_D),
- OPC_CMP_NGT_D = FOP (63, FMT_D),
+ OPC_CMP_F_D = FOP(48, FMT_D),
+ OPC_CMP_UN_D = FOP(49, FMT_D),
+ OPC_CMP_EQ_D = FOP(50, FMT_D),
+ OPC_CMP_UEQ_D = FOP(51, FMT_D),
+ OPC_CMP_OLT_D = FOP(52, FMT_D),
+ OPC_CMP_ULT_D = FOP(53, FMT_D),
+ OPC_CMP_OLE_D = FOP(54, FMT_D),
+ OPC_CMP_ULE_D = FOP(55, FMT_D),
+ OPC_CMP_SF_D = FOP(56, FMT_D),
+ OPC_CMP_NGLE_D = FOP(57, FMT_D),
+ OPC_CMP_SEQ_D = FOP(58, FMT_D),
+ OPC_CMP_NGL_D = FOP(59, FMT_D),
+ OPC_CMP_LT_D = FOP(60, FMT_D),
+ OPC_CMP_NGE_D = FOP(61, FMT_D),
+ OPC_CMP_LE_D = FOP(62, FMT_D),
+ OPC_CMP_NGT_D = FOP(63, FMT_D),
OPC_CVT_S_W = FOP(32, FMT_W),
OPC_CVT_D_W = FOP(33, FMT_W),
@@ -10568,22 +10570,22 @@ enum fopcode {
OPC_PLU_PS = FOP(45, FMT_PS),
OPC_PUL_PS = FOP(46, FMT_PS),
OPC_PUU_PS = FOP(47, FMT_PS),
- OPC_CMP_F_PS = FOP (48, FMT_PS),
- OPC_CMP_UN_PS = FOP (49, FMT_PS),
- OPC_CMP_EQ_PS = FOP (50, FMT_PS),
- OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
- OPC_CMP_OLT_PS = FOP (52, FMT_PS),
- OPC_CMP_ULT_PS = FOP (53, FMT_PS),
- OPC_CMP_OLE_PS = FOP (54, FMT_PS),
- OPC_CMP_ULE_PS = FOP (55, FMT_PS),
- OPC_CMP_SF_PS = FOP (56, FMT_PS),
- OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
- OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
- OPC_CMP_NGL_PS = FOP (59, FMT_PS),
- OPC_CMP_LT_PS = FOP (60, FMT_PS),
- OPC_CMP_NGE_PS = FOP (61, FMT_PS),
- OPC_CMP_LE_PS = FOP (62, FMT_PS),
- OPC_CMP_NGT_PS = FOP (63, FMT_PS),
+ OPC_CMP_F_PS = FOP(48, FMT_PS),
+ OPC_CMP_UN_PS = FOP(49, FMT_PS),
+ OPC_CMP_EQ_PS = FOP(50, FMT_PS),
+ OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
+ OPC_CMP_OLT_PS = FOP(52, FMT_PS),
+ OPC_CMP_ULT_PS = FOP(53, FMT_PS),
+ OPC_CMP_OLE_PS = FOP(54, FMT_PS),
+ OPC_CMP_ULE_PS = FOP(55, FMT_PS),
+ OPC_CMP_SF_PS = FOP(56, FMT_PS),
+ OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
+ OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
+ OPC_CMP_NGL_PS = FOP(59, FMT_PS),
+ OPC_CMP_LT_PS = FOP(60, FMT_PS),
+ OPC_CMP_NGE_PS = FOP(61, FMT_PS),
+ OPC_CMP_LE_PS = FOP(62, FMT_PS),
+ OPC_CMP_NGT_PS = FOP(63, FMT_PS),
};
enum r6_f_cmp_op {
@@ -10633,7 +10635,8 @@ enum r6_f_cmp_op {
R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
};
-static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
+
+static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
{
TCGv t0 = tcg_temp_new();
@@ -10714,7 +10717,7 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
tcg_temp_free(t0);
}
-static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
+static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
{
TCGLabel *l1;
TCGCond cond;
@@ -10763,7 +10766,8 @@ static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
tcg_temp_free_i32(t0);
}
-static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
+static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
+ int tf)
{
int cond;
TCGv_i32 t0 = tcg_temp_new_i32();
@@ -10886,8 +10890,8 @@ static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
tcg_temp_free_i64(t1);
}
-static void gen_farith (DisasContext *ctx, enum fopcode op1,
- int ft, int fs, int fd, int cc)
+static void gen_farith(DisasContext *ctx, enum fopcode op1,
+ int ft, int fs, int fd, int cc)
{
uint32_t func = ctx->opcode & 0x3f;
switch (op1) {
@@ -12314,8 +12318,8 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
}
/* Coprocessor 3 (FPU) */
-static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
- int fd, int fs, int base, int index)
+static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
+ int fd, int fs, int base, int index)
{
TCGv t0 = tcg_temp_new();
@@ -12394,8 +12398,8 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
tcg_temp_free(t0);
}
-static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
- int fd, int fr, int fs, int ft)
+static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
+ int fd, int fr, int fs, int ft)
{
switch (opc) {
case OPC_ALNV_PS:
@@ -13157,17 +13161,17 @@ enum {
RR_RY_CNVT_SEW = 0x6,
};
-static int xlat (int r)
+static int xlat(int r)
{
static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
return map[r];
}
-static void gen_mips16_save (DisasContext *ctx,
- int xsregs, int aregs,
- int do_ra, int do_s0, int do_s1,
- int framesize)
+static void gen_mips16_save(DisasContext *ctx,
+ int xsregs, int aregs,
+ int do_ra, int do_s0, int do_s1,
+ int framesize)
{
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
@@ -13322,10 +13326,10 @@ static void gen_mips16_save (DisasContext *ctx,
tcg_temp_free(t2);
}
-static void gen_mips16_restore (DisasContext *ctx,
- int xsregs, int aregs,
- int do_ra, int do_s0, int do_s1,
- int framesize)
+static void gen_mips16_restore(DisasContext *ctx,
+ int xsregs, int aregs,
+ int do_ra, int do_s0, int do_s1,
+ int framesize)
{
int astatic;
TCGv t0 = tcg_temp_new();
@@ -13428,8 +13432,8 @@ static void gen_mips16_restore (DisasContext *ctx,
tcg_temp_free(t2);
}
-static void gen_addiupc (DisasContext *ctx, int rx, int imm,
- int is_64_bit, int extended)
+static void gen_addiupc(DisasContext *ctx, int rx, int imm,
+ int is_64_bit, int extended)
{
TCGv t0;
@@ -13459,9 +13463,9 @@ static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
}
#if defined(TARGET_MIPS64)
-static void decode_i64_mips16 (DisasContext *ctx,
- int ry, int funct, int16_t offset,
- int extended)
+static void decode_i64_mips16(DisasContext *ctx,
+ int ry, int funct, int16_t offset,
+ int extended)
{
switch (funct) {
case I64_LDSP:
@@ -13520,7 +13524,7 @@ static void decode_i64_mips16 (DisasContext *ctx,
}
#endif
-static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
+static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
{
int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
int op, rx, ry, funct, sa;
@@ -13734,7 +13738,7 @@ static inline void gen_helper_do_semihosting(void *env)
}
#endif
-static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
+static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
{
int rx, ry;
int sa;
@@ -13957,7 +13961,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
case M16_OPC_LWPC:
gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
break;
-#if defined (TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case M16_OPC_LWU:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
@@ -14061,7 +14065,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
case RR_SRAV:
gen_shift(ctx, OPC_SRAV, ry, rx, ry);
break;
-#if defined (TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case RR_DSRL:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
@@ -14124,7 +14128,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
case RR_MFLO:
gen_HILO(ctx, OPC_MFLO, 0, rx);
break;
-#if defined (TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case RR_DSRA:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
@@ -14158,7 +14162,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
case RR_DIVU:
gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
break;
-#if defined (TARGET_MIPS64)
+#if defined(TARGET_MIPS64)
case RR_DMULT:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
@@ -14802,7 +14806,7 @@ enum {
ADDIUR1SP = 0x1
};
-static int mmreg (int r)
+static int mmreg(int r)
{
static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
@@ -14810,7 +14814,7 @@ static int mmreg (int r)
}
/* Used for 16-bit store instructions. */
-static int mmreg2 (int r)
+static int mmreg2(int r)
{
static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
@@ -14885,8 +14889,8 @@ static void gen_andi16(DisasContext *ctx)
gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
}
-static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
- int base, int16_t offset)
+static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
+ int base, int16_t offset)
{
TCGv t0, t1;
TCGv_i32 t2;
@@ -15159,7 +15163,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx)
}
}
-static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
+static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
{
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
@@ -15179,8 +15183,8 @@ static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
tcg_temp_free(t1);
}
-static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
- int base, int16_t offset)
+static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
+ int base, int16_t offset)
{
TCGv t0, t1;
@@ -15205,14 +15209,14 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
tcg_gen_movi_tl(t1, 4);
gen_op_addr_add(ctx, t0, t0, t1);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
- gen_store_gpr(t1, rd+1);
+ gen_store_gpr(t1, rd + 1);
break;
case SWP:
gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
tcg_gen_movi_tl(t1, 4);
gen_op_addr_add(ctx, t0, t0, t1);
- gen_load_gpr(t1, rd+1);
+ gen_load_gpr(t1, rd + 1);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
break;
#ifdef TARGET_MIPS64
@@ -15226,14 +15230,14 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
tcg_gen_movi_tl(t1, 8);
gen_op_addr_add(ctx, t0, t0, t1);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
- gen_store_gpr(t1, rd+1);
+ gen_store_gpr(t1, rd + 1);
break;
case SDP:
gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_movi_tl(t1, 8);
gen_op_addr_add(ctx, t0, t0, t1);
- gen_load_gpr(t1, rd+1);
+ gen_load_gpr(t1, rd + 1);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
break;
#endif
@@ -15270,7 +15274,7 @@ static void gen_sync(int stype)
tcg_gen_mb(tcg_mo);
}
-static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
+static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
{
int extension = (ctx->opcode >> 6) & 0x3f;
int minor = (ctx->opcode >> 12) & 0xf;
@@ -17234,7 +17238,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
}
}
-static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
+static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
{
uint32_t op;
@@ -27881,11 +27885,11 @@ static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
eval_big = 0x8000000000000000ULL;
break;
}
- tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
- tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
+ tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
+ tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
tcg_gen_andi_i64(t0, t0, eval_big);
- tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
- tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
+ tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
+ tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
tcg_gen_andi_i64(t1, t1, eval_big);
tcg_gen_or_i64(t0, t0, t1);
/* if all bits are zero then all elements are not zero */
@@ -27913,7 +27917,7 @@ static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
case OPC_BNZ_V:
{
TCGv_i64 t0 = tcg_temp_new_i64();
- tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
+ tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
tcg_gen_trunc_i64_tl(bcond, t0);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2 0/3] ceph: don't NULL terminate virtual xattr values
From: Andy Shevchenko @ 2019-06-20 10:24 UTC (permalink / raw)
To: Jeff Layton
Cc: linux-kernel, ceph-devel, idryomov, zyan, sage, agruenba, joe,
pmladek, rostedt, geert+renesas
In-Reply-To: <20190619164528.31958-1-jlayton@kernel.org>
On Wed, Jun 19, 2019 at 12:45:25PM -0400, Jeff Layton wrote:
> v2: drop bogus EXPORT_SYMBOL of static function
>
> The only real difference between this set and the one I sent originally
> is the removal of a spurious EXPORT_SYMBOL in the snprintf patch.
>
> I'm mostly sending this with a wider cc list in an effort to get a
> review from the maintainers of the printf code. Basically ceph needs a
> snprintf variant that does not NULL terminate in order to handle its
> virtual xattrs.
>
> Joe Perches had expressed some concerns about stack usage in vsnprintf
> with this, but I'm not sure I really understand the basis of that
> concern. If it is problematic, then I could use suggestions as to how
> best to fix that up.
It might be problematic, since vsnprintf() can be called recursively.
> ----------------------------8<-----------------------------
>
> kcephfs has several "virtual" xattrs that return strings that are
> currently populated using snprintf(), which always NULL terminates the
> string.
>
> This leads to the string being truncated when we use a buffer length
> acquired by calling getxattr with a 0 size first. The last character
> of the string ends up being clobbered by the termination.
So, then don't use snprintf() for this, simple memcpy() designed for that kind
of things.
> The convention with xattrs is to not store the termination with string
> data, given that we have the length. This is how setfattr/getfattr
> operate.
Fine.
> This patch makes ceph's virtual xattrs not include NULL termination
> when formatting their values. In order to handle this, a new
> snprintf_noterm function is added, and ceph is changed over to use
> this to populate the xattr value buffer.
In terms of vsnprintf(), and actually compiler point of view, it's not a string
anymore, it's a text-based data.
Personally, I don't see an advantage of a deep intrusion into vsnprintf().
The wrapper can be made to achieve this w/o touching the generic code. Thus,
you can quickly and cleanly fix the issue, while discussing this with wider
audience.
> Finally, we fix ceph to
> return -ERANGE properly when the string didn't fit in the buffer.
>
> Jeff Layton (3):
> lib/vsprintf: add snprintf_noterm
> ceph: don't NULL terminate virtual xattr strings
> ceph: return -ERANGE if virtual xattr value didn't fit in buffer
>
> fs/ceph/xattr.c | 49 +++++++-------
> include/linux/kernel.h | 2 +
> lib/vsprintf.c | 144 ++++++++++++++++++++++++++++-------------
> 3 files changed, 129 insertions(+), 66 deletions(-)
>
> --
> 2.21.0
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [dpdk-dev] [PATCH v7 6/6] doc: update docs for ntb driver
From: Xiaoyun Li @ 2019-06-20 10:21 UTC (permalink / raw)
To: jingjing.wu, keith.wiles, cunming.liang, omkar.maslekar; +Cc: dev, Xiaoyun Li
In-Reply-To: <20190620102147.41557-1-xiaoyun.li@intel.com>
Update related documents for ntb pmd and example.
Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
---
MAINTAINERS | 8 +++++
doc/guides/rawdevs/index.rst | 1 +
doc/guides/rawdevs/ntb_rawdev.rst | 41 ++++++++++++++++++++++
doc/guides/rel_notes/release_19_08.rst | 15 ++++++++
doc/guides/sample_app_ug/index.rst | 1 +
doc/guides/sample_app_ug/ntb.rst | 47 ++++++++++++++++++++++++++
6 files changed, 113 insertions(+)
create mode 100644 doc/guides/rawdevs/ntb_rawdev.rst
create mode 100644 doc/guides/sample_app_ug/ntb.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index fdc083db9..8c919484d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1057,6 +1057,10 @@ M: Nipun Gupta <nipun.gupta@nxp.com>
F: drivers/raw/dpaa2_cmdif/
F: doc/guides/rawdevs/dpaa2_cmdif.rst
+NTB Rawdev
+M: Xiaoyun Li <xiaoyun.li@intel.com>
+F: drivers/raw/ntb_rawdev/
+F: doc/guides/rawdevs/ntb_rawdev.rst
Packet processing
-----------------
@@ -1433,3 +1437,7 @@ F: examples/tep_termination/
F: examples/vmdq/
F: examples/vmdq_dcb/
F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
+
+M: Xiaoyun Li <xiaoyun.li@intel.com>
+F: examples/ntb/
+F: doc/guides/sample_app_ug/ntb.rst
diff --git a/doc/guides/rawdevs/index.rst b/doc/guides/rawdevs/index.rst
index 7c3bd9586..cf6fcb06b 100644
--- a/doc/guides/rawdevs/index.rst
+++ b/doc/guides/rawdevs/index.rst
@@ -14,3 +14,4 @@ application through rawdev API.
dpaa2_cmdif
dpaa2_qdma
ifpga_rawdev
+ ntb_rawdev
diff --git a/doc/guides/rawdevs/ntb_rawdev.rst b/doc/guides/rawdevs/ntb_rawdev.rst
new file mode 100644
index 000000000..429e2af3e
--- /dev/null
+++ b/doc/guides/rawdevs/ntb_rawdev.rst
@@ -0,0 +1,41 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright(c) 2018 Intel Corporation.
+
+NTB Rawdev Driver
+=================
+
+The ``ntb`` rawdev driver provides a non-transparent bridge between two
+separate hosts so that they can communicate with each other. Thus, many
+user cases can benefit from this, such as fault tolerance and visual
+acceleration.
+
+This PMD allows two hosts to handshake for device start and stop, memory
+allocation for the peer to access and read/write allocated memory from peer.
+Also, the PMD allows to use doorbell registers to notify the peer and share
+some information by using scratchpad registers.
+
+But the PMD hasn't implemented FIFO. The FIFO will come in 19.11 release.
+And this PMD only supports intel skylake platform.
+
+BIOS setting on skylake platform
+--------------------------------
+
+Intel non-transparent bridge needs special BIOS setting. Since the PMD only
+supports intel skylake platform, introduce BIOS setting here. The referencce
+is https://www.intel.com/content/dam/support/us/en/documents/server-products/Intel_Xeon_Processor_Scalable_Family_BIOS_User_Guide.pdf
+
+- Set the needed PCIe port as NTB to NTB mode on both hosts.
+- Enable NTB bars and set bar size of bar 23 and bar 45 as 12-29 (2K-512M)
+ on both hosts. Note that bar size on both hosts should be the same.
+- Disable split bars for both hosts.
+- Set crosslink control override as DSD/USP on one host, USD/DSP on
+ another host.
+- Disable PCIe PII SSC (Spread Spectrum Clocking) for both hosts. This
+ is a hardware requirement.
+
+Build options
+-------------
+
+- ``CONFIG_RTE_LIBRTE_IFPGA_RAWDEV`` (default ``y``)
+
+ Toggle compilation of the ``ntb_rawdev`` driver.
diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst
index 563999d57..3a35ffbd7 100644
--- a/doc/guides/rel_notes/release_19_08.rst
+++ b/doc/guides/rel_notes/release_19_08.rst
@@ -94,6 +94,21 @@ New Features
* Enabled Tx outer/inner L3/L4 checksum offload.
+* **Introduced NTB PMD.**
+
+ The PMD provided a non-transparent bridge between two separate hosts so
+ that they can communicate with each other. Thus, many user cases can
+ benefit from this, such as fault tolerance and visual acceleration.
+
+ This PMD implemented the following features:
+ * Handshake for device start and stop between two hosts.
+ * Memory allocation for the peer to access and read/write allocated
+ memory from peer.
+ * Use doorbell registers to notify the peer and share some information
+ by using scratchpad registers.
+
+ But the PMD hasn't implemented FIFO. The FIFO will come in 19.11 release.
+ And this PMD only supports intel skylake platform.
Removed Items
-------------
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 2945be08f..f23f8f59e 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -58,3 +58,4 @@ Sample Applications User Guides
fips_validation
ipsec_secgw
bbdev_app
+ ntb
diff --git a/doc/guides/sample_app_ug/ntb.rst b/doc/guides/sample_app_ug/ntb.rst
new file mode 100644
index 000000000..079242175
--- /dev/null
+++ b/doc/guides/sample_app_ug/ntb.rst
@@ -0,0 +1,47 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright(c) 2019 Intel Corporation.
+
+NTB Sample Application
+======================
+
+The ntb sample application shows how to use ntb rawdev driver.
+This sample provides interactive mode to transmit file between
+two hosts.
+
+Compiling the Application
+-------------------------
+
+To compile the sample application see :doc:`compiling`.
+
+The application is located in the ``ntb`` sub-directory.
+
+Running the Application
+-----------------------
+
+The application requires an available core for each port, plus one.
+The only available options are the standard ones for the EAL:
+
+.. code-block:: console
+
+ ./build/ntb_fwd -c 0xf -n 6 -- -i
+
+Refer to the *DPDK Getting Started Guide* for general information on
+running applications and the Environment Abstraction Layer (EAL)
+options.
+
+Using the application
+---------------------
+
+The application is console-driven using the cmdline DPDK interface:
+
+.. code-block:: console
+
+ ntb>
+
+From this interface the available commands and descriptions of what
+they do as as follows:
+
+* ``send [filepath]``: Send file to the peer host.
+* ``receive [filepath]``: Receive file to [filepath]. Need the peer
+ to send file successfully first.
+* ``quit``: Exit program
--
2.17.1
^ permalink raw reply related
* [dpdk-dev] [PATCH v7 5/6] usertools/dpdk-devbind.py: add support for ntb
From: Xiaoyun Li @ 2019-06-20 10:21 UTC (permalink / raw)
To: jingjing.wu, keith.wiles, cunming.liang, omkar.maslekar; +Cc: dev, Xiaoyun Li
In-Reply-To: <20190620102147.41557-1-xiaoyun.li@intel.com>
In order to allow binding/unbinding of devices for use by the
ntb_rawdev, we need to update the devbind script to add a new class
of device, and add device ids for the specific HW instances. And
only support skx platform right now.
Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
---
usertools/dpdk-devbind.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/usertools/dpdk-devbind.py b/usertools/dpdk-devbind.py
index 9e79f0d28..6e6f64bd3 100755
--- a/usertools/dpdk-devbind.py
+++ b/usertools/dpdk-devbind.py
@@ -36,11 +36,15 @@
octeontx2_npa = {'Class': '08', 'Vendor': '177d', 'Device': 'a0fb,a0fc',
'SVendor': None, 'SDevice': None}
+intel_ntb_skx = {'Class': '06', 'Vendor': '8086', 'Device': '201c',
+ 'SVendor': None, 'SDevice': None}
+
network_devices = [network_class, cavium_pkx, avp_vnic, ifpga_class]
crypto_devices = [encryption_class, intel_processor_class]
eventdev_devices = [cavium_sso, cavium_tim, octeontx2_sso]
mempool_devices = [cavium_fpa, octeontx2_npa]
compress_devices = [cavium_zip]
+misc_devices = [intel_ntb_skx]
# global dict ethernet devices present. Dictionary indexed by PCI address.
# Each device within this is itself a dictionary of device properties
@@ -595,6 +599,9 @@ def show_status():
if status_dev == "compress" or status_dev == "all":
show_device_status(compress_devices , "Compress")
+ if status_dev == "misc" or status_dev == "all":
+ show_device_status(misc_devices , "Misc")
+
def parse_args():
'''Parses the command-line arguments given by the user and takes the
@@ -670,6 +677,7 @@ def do_arg_actions():
get_device_details(eventdev_devices)
get_device_details(mempool_devices)
get_device_details(compress_devices)
+ get_device_details(misc_devices)
show_status()
@@ -690,6 +698,7 @@ def main():
get_device_details(eventdev_devices)
get_device_details(mempool_devices)
get_device_details(compress_devices)
+ get_device_details(misc_devices)
do_arg_actions()
if __name__ == "__main__":
--
2.17.1
^ permalink raw reply related
* [dpdk-dev] [PATCH v7 4/6] examples/ntb: enable an example for ntb
From: Xiaoyun Li @ 2019-06-20 10:21 UTC (permalink / raw)
To: jingjing.wu, keith.wiles, cunming.liang, omkar.maslekar; +Cc: dev, Xiaoyun Li
In-Reply-To: <20190620102147.41557-1-xiaoyun.li@intel.com>
Enable an example for rawdev ntb. Support interactive mode to send
file on one host and receive file from another host. The command line
would be 'send [filepath]' and 'receive [filepath]'.
But since the FIFO is not enabled right now, use rte_memcpy as the enqueue
and dequeue functions and only support transmitting file no more than 4M.
Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
---
drivers/raw/ntb_rawdev/ntb_rawdev.c | 28 ++-
examples/Makefile | 1 +
examples/meson.build | 2 +-
examples/ntb/Makefile | 68 +++++
examples/ntb/meson.build | 16 ++
examples/ntb/ntb_fwd.c | 377 ++++++++++++++++++++++++++++
6 files changed, 483 insertions(+), 9 deletions(-)
create mode 100644 examples/ntb/Makefile
create mode 100644 examples/ntb/meson.build
create mode 100644 examples/ntb/ntb_fwd.c
diff --git a/drivers/raw/ntb_rawdev/ntb_rawdev.c b/drivers/raw/ntb_rawdev/ntb_rawdev.c
index e4ae95a01..145c77bd7 100644
--- a/drivers/raw/ntb_rawdev/ntb_rawdev.c
+++ b/drivers/raw/ntb_rawdev/ntb_rawdev.c
@@ -240,11 +240,19 @@ ntb_enqueue_bufs(struct rte_rawdev *dev,
unsigned int count,
rte_rawdev_obj_t context)
{
- RTE_SET_USED(dev);
- RTE_SET_USED(buffers);
- RTE_SET_USED(count);
- RTE_SET_USED(context);
+ /* Not FIFO right now. Just for testing memory write. */
+ struct ntb_hw *hw = dev->dev_private;
+ unsigned int i;
+ void *bar_addr;
+ size_t size;
+
+ if (hw->ntb_ops->get_peer_mw_addr == NULL)
+ return -ENOTSUP;
+ bar_addr = (*hw->ntb_ops->get_peer_mw_addr)(dev, 0);
+ size = (size_t)context;
+ for (i = 0; i < count; i++)
+ rte_memcpy(bar_addr, buffers[i]->buf_addr, size);
return 0;
}
@@ -254,11 +262,15 @@ ntb_dequeue_bufs(struct rte_rawdev *dev,
unsigned int count,
rte_rawdev_obj_t context)
{
- RTE_SET_USED(dev);
- RTE_SET_USED(buffers);
- RTE_SET_USED(count);
- RTE_SET_USED(context);
+ /* Not FIFO. Just for testing memory read. */
+ struct ntb_hw *hw = dev->dev_private;
+ unsigned int i;
+ size_t size;
+
+ size = (size_t)context;
+ for (i = 0; i < count; i++)
+ rte_memcpy(buffers[i]->buf_addr, hw->mz[i]->addr, size);
return 0;
}
diff --git a/examples/Makefile b/examples/Makefile
index 7562424d9..de11dd487 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -53,6 +53,7 @@ DIRS-y += link_status_interrupt
DIRS-$(CONFIG_RTE_LIBRTE_LPM) += load_balancer
DIRS-y += multi_process
DIRS-y += netmap_compat/bridge
+DIRS-y += ntb
DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += packet_ordering
ifeq ($(CONFIG_RTE_ARCH_X86_64),y)
DIRS-y += performance-thread
diff --git a/examples/meson.build b/examples/meson.build
index c695d52c9..2a4a084af 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -30,7 +30,7 @@ all_examples = [
'multi_process/hotplug_mp',
'multi_process/simple_mp',
'multi_process/symmetric_mp',
- 'netmap_compat', 'packet_ordering',
+ 'netmap_compat', 'ntb', 'packet_ordering',
'performance-thread', 'ptpclient',
'qos_meter', 'qos_sched',
'quota_watermark', 'rxtx_callbacks',
diff --git a/examples/ntb/Makefile b/examples/ntb/Makefile
new file mode 100644
index 000000000..5ddd9b95f
--- /dev/null
+++ b/examples/ntb/Makefile
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+# binary name
+APP = ntb_fwd
+
+# all source are stored in SRCS-y
+SRCS-y := ntb_fwd.c
+
+# Build using pkg-config variables if possible
+$(shell pkg-config --exists libdpdk)
+ifeq ($(.SHELLSTATUS),0)
+
+all: shared
+.PHONY: shared static
+shared: build/$(APP)-shared
+ ln -sf $(APP)-shared build/$(APP)
+static: build/$(APP)-static
+ ln -sf $(APP)-static build/$(APP)
+
+CFLAGS += -D_FILE_OFFSET_BITS=64
+LDFLAGS += -pthread
+
+PC_FILE := $(shell pkg-config --path libdpdk)
+CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
+LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
+LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+
+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
+ $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
+
+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
+ $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
+
+build:
+ @mkdir -p $@
+
+.PHONY: clean
+clean:
+ rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
+ rmdir --ignore-fail-on-non-empty build
+
+else # Build using legacy build system
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
+$(info This application can only operate in a linuxapp environment, \
+please change the definition of the RTE_TARGET environment variable)
+all:
+else
+
+CFLAGS += -D_FILE_OFFSET_BITS=64
+CFLAGS += -O2
+CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
+endif
+endif
diff --git a/examples/ntb/meson.build b/examples/ntb/meson.build
new file mode 100644
index 000000000..9a6288f4f
--- /dev/null
+++ b/examples/ntb/meson.build
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+# meson file, for building this example as part of a main DPDK build.
+#
+# To build this example as a standalone application with an already-installed
+# DPDK instance, use 'make'
+
+if host_machine.system() != 'linux'
+ build = false
+endif
+deps += 'rawdev'
+cflags += ['-D_FILE_OFFSET_BITS=64']
+sources = files(
+ 'ntb_fwd.c'
+)
diff --git a/examples/ntb/ntb_fwd.c b/examples/ntb/ntb_fwd.c
new file mode 100644
index 000000000..c169f01a3
--- /dev/null
+++ b/examples/ntb/ntb_fwd.c
@@ -0,0 +1,377 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <cmdline_parse_string.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+#include <rte_common.h>
+#include <rte_rawdev.h>
+#include <rte_lcore.h>
+
+#define NTB_DRV_NAME_LEN 7
+static uint64_t max_file_size = 0x400000;
+static uint8_t interactive = 1;
+static uint16_t dev_id;
+
+/* *** Help command with introduction. *** */
+struct cmd_help_result {
+ cmdline_fixed_string_t help;
+};
+
+static void cmd_help_parsed(__attribute__((unused)) void *parsed_result,
+ struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ cmdline_printf(
+ cl,
+ "\n"
+ "The following commands are currently available:\n\n"
+ "Control:\n"
+ " quit :"
+ " Quit the application.\n"
+ "\nFile transmit:\n"
+ " send [path] :"
+ " Send [path] file. (No more than %"PRIu64")\n"
+ " recv [path] :"
+ " Receive file to [path]. Make sure sending is done"
+ " on the other side.\n",
+ max_file_size
+ );
+
+}
+
+cmdline_parse_token_string_t cmd_help_help =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help");
+
+cmdline_parse_inst_t cmd_help = {
+ .f = cmd_help_parsed,
+ .data = NULL,
+ .help_str = "show help",
+ .tokens = {
+ (void *)&cmd_help_help,
+ NULL,
+ },
+};
+
+/* *** QUIT *** */
+struct cmd_quit_result {
+ cmdline_fixed_string_t quit;
+};
+
+static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
+ struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ /* Stop traffic and Close port. */
+ rte_rawdev_stop(dev_id);
+ rte_rawdev_close(dev_id);
+
+ cmdline_quit(cl);
+}
+
+cmdline_parse_token_string_t cmd_quit_quit =
+ TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
+
+cmdline_parse_inst_t cmd_quit = {
+ .f = cmd_quit_parsed,
+ .data = NULL,
+ .help_str = "exit application",
+ .tokens = {
+ (void *)&cmd_quit_quit,
+ NULL,
+ },
+};
+
+/* *** SEND FILE PARAMETERS *** */
+struct cmd_sendfile_result {
+ cmdline_fixed_string_t send_string;
+ char filepath[];
+};
+
+static void
+cmd_sendfile_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_sendfile_result *res = parsed_result;
+ struct rte_rawdev_buf *pkts_send[1];
+ uint64_t rsize, size, link;
+ uint8_t *buff;
+ uint32_t val;
+ FILE *file;
+
+ if (!rte_rawdevs[dev_id].started) {
+ printf("Device needs to be up first. Try later.\n");
+ return;
+ }
+
+ rte_rawdev_get_attr(dev_id, "link_status", &link);
+ if (!link) {
+ printf("Link is not up, cannot send file.\n");
+ return;
+ }
+
+ file = fopen(res->filepath, "r");
+ if (file == NULL) {
+ printf("Fail to open the file.\n");
+ return;
+ }
+
+ fseek(file, 0, SEEK_END);
+ size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ /**
+ * No FIFO now. Only test memory. Limit sending file
+ * size <= max_file_size.
+ */
+ if (size > max_file_size) {
+ printf("Warning: The file is too large. Only send first"
+ " %"PRIu64" bits.\n", max_file_size);
+ size = max_file_size;
+ }
+
+ buff = (uint8_t *)malloc(size);
+ rsize = fread(buff, size, 1, file);
+ if (rsize != 1) {
+ printf("Fail to read file.\n");
+ fclose(file);
+ free(buff);
+ return;
+ }
+
+ /* Tell remote about the file size. */
+ val = size >> 32;
+ rte_rawdev_set_attr(dev_id, "spad_user_0", val);
+ val = size;
+ rte_rawdev_set_attr(dev_id, "spad_user_1", val);
+
+ pkts_send[0] = (struct rte_rawdev_buf *)malloc
+ (sizeof(struct rte_rawdev_buf));
+ pkts_send[0]->buf_addr = buff;
+
+ if (rte_rawdev_enqueue_buffers(dev_id, pkts_send, 1,
+ (void *)(size_t)size)) {
+ printf("Fail to enqueue.\n");
+ goto clean;
+ }
+ printf("Done sending file.\n");
+
+clean:
+ fclose(file);
+ free(buff);
+ free(pkts_send[0]);
+}
+
+cmdline_parse_token_string_t cmd_send_file_send =
+ TOKEN_STRING_INITIALIZER(struct cmd_sendfile_result, send_string,
+ "send");
+cmdline_parse_token_string_t cmd_send_file_filepath =
+ TOKEN_STRING_INITIALIZER(struct cmd_sendfile_result, filepath, NULL);
+
+
+cmdline_parse_inst_t cmd_send_file = {
+ .f = cmd_sendfile_parsed,
+ .data = NULL,
+ .help_str = "send <file_path>",
+ .tokens = {
+ (void *)&cmd_send_file_send,
+ (void *)&cmd_send_file_filepath,
+ NULL,
+ },
+};
+
+/* *** RECEIVE FILE PARAMETERS *** */
+struct cmd_recvfile_result {
+ cmdline_fixed_string_t recv_string;
+ char filepath[];
+};
+
+static void
+cmd_recvfile_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_sendfile_result *res = parsed_result;
+ struct rte_rawdev_buf *pkts_recv[1];
+ uint8_t *buff;
+ uint64_t val;
+ size_t size;
+ FILE *file;
+
+ if (!rte_rawdevs[dev_id].started) {
+ printf("Device needs to be up first. Try later.\n");
+ return;
+ }
+
+ rte_rawdev_get_attr(dev_id, "link_status", &val);
+ if (!val) {
+ printf("Link is not up, cannot receive file.\n");
+ return;
+ }
+
+ file = fopen(res->filepath, "w");
+ if (file == NULL) {
+ printf("Fail to open the file.\n");
+ return;
+ }
+
+ rte_rawdev_get_attr(dev_id, "spad_user_0", &val);
+ size = val << 32;
+ rte_rawdev_get_attr(dev_id, "spad_user_1", &val);
+ size |= val;
+
+ buff = (uint8_t *)malloc(size);
+ pkts_recv[0] = (struct rte_rawdev_buf *)malloc
+ (sizeof(struct rte_rawdev_buf));
+ pkts_recv[0]->buf_addr = buff;
+
+ if (rte_rawdev_dequeue_buffers(dev_id, pkts_recv, 1, (void *)size)) {
+ printf("Fail to dequeue.\n");
+ goto clean;
+ }
+
+ fwrite(buff, size, 1, file);
+ printf("Done receiving to file.\n");
+
+clean:
+ fclose(file);
+ free(buff);
+ free(pkts_recv[0]);
+}
+
+cmdline_parse_token_string_t cmd_recv_file_recv =
+ TOKEN_STRING_INITIALIZER(struct cmd_recvfile_result, recv_string,
+ "recv");
+cmdline_parse_token_string_t cmd_recv_file_filepath =
+ TOKEN_STRING_INITIALIZER(struct cmd_recvfile_result, filepath, NULL);
+
+
+cmdline_parse_inst_t cmd_recv_file = {
+ .f = cmd_recvfile_parsed,
+ .data = NULL,
+ .help_str = "recv <file_path>",
+ .tokens = {
+ (void *)&cmd_recv_file_recv,
+ (void *)&cmd_recv_file_filepath,
+ NULL,
+ },
+};
+
+/* list of instructions */
+cmdline_parse_ctx_t main_ctx[] = {
+ (cmdline_parse_inst_t *)&cmd_help,
+ (cmdline_parse_inst_t *)&cmd_send_file,
+ (cmdline_parse_inst_t *)&cmd_recv_file,
+ (cmdline_parse_inst_t *)&cmd_quit,
+ NULL,
+};
+
+/* prompt function, called from main on MASTER lcore */
+static void
+prompt(void)
+{
+ struct cmdline *cl;
+
+ cl = cmdline_stdin_new(main_ctx, "ntb> ");
+ if (cl == NULL)
+ return;
+
+ cmdline_interact(cl);
+ cmdline_stdin_exit(cl);
+}
+
+static void
+signal_handler(int signum)
+{
+ if (signum == SIGINT || signum == SIGTERM) {
+ printf("\nSignal %d received, preparing to exit...\n", signum);
+ signal(signum, SIG_DFL);
+ kill(getpid(), signum);
+ }
+}
+
+static void
+ntb_usage(const char *prgname)
+{
+ printf("%s [EAL options] -- [options]\n"
+ "-i : run in interactive mode (default value is 1)\n",
+ prgname);
+}
+
+static int
+parse_args(int argc, char **argv)
+{
+ char *prgname = argv[0], **argvopt = argv;
+ int opt, ret;
+
+ /* Only support interactive mode to send/recv file first. */
+ while ((opt = getopt(argc, argvopt, "i")) != EOF) {
+ switch (opt) {
+ case 'i':
+ printf("Interactive-mode selected\n");
+ interactive = 1;
+ break;
+
+ default:
+ ntb_usage(prgname);
+ return -1;
+ }
+ }
+
+ if (optind >= 0)
+ argv[optind-1] = prgname;
+
+ ret = optind-1;
+ optind = 1; /* reset getopt lib */
+ return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret, i;
+
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Error with EAL initialization.\n");
+
+ /* Find 1st ntb rawdev. */
+ for (i = 0; i < RTE_RAWDEV_MAX_DEVS; i++)
+ if (rte_rawdevs[i].driver_name &&
+ (strncmp(rte_rawdevs[i].driver_name, "raw_ntb",
+ NTB_DRV_NAME_LEN) == 0) && (rte_rawdevs[i].attached == 1))
+ break;
+
+ if (i == RTE_RAWDEV_MAX_DEVS)
+ rte_exit(EXIT_FAILURE, "Cannot find any ntb device.\n");
+
+ dev_id = i;
+
+ argc -= ret;
+ argv += ret;
+
+ ret = parse_args(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid arguments\n");
+
+ rte_rawdev_start(dev_id);
+
+ if (interactive) {
+ sleep(1);
+ prompt();
+ }
+
+ return 0;
+}
--
2.17.1
^ permalink raw reply related
* Re: [PATCH] hung_task: recover hung task warnings in next check interval
From: Tetsuo Handa @ 2019-06-20 10:23 UTC (permalink / raw)
To: Yafang Shao; +Cc: Andrew Morton, Dmitry Vyukov, LKML
In-Reply-To: <CALOAHbCe9J0pOCW03dW+C4NK__amTKttAs=eNHXwvPPf5Lpwhw@mail.gmail.com>
On 2019/06/20 19:10, Yafang Shao wrote:
>>> With this patch, hung task warnings will be reset with
>>> sys_hung_task_warnings setting in evenry check interval.
>>
>> Since it is uncommon that the messages are printed for more than 10
>> times for one check_hung_uninterruptible_tasks() call, this patch is
>> effectively changing to always print the messages (in other words,
>> setting -1).
>
> If sys_hung_task_warnings can't be recovered, does it make sense to exist?
> In which case do we need this setting ?
Someone might want to print the messages up to only a few times because he/she
does not like the ever-repeating messages. But automatically resetting will
forbid his/her wish to print the messages for up to only a few times.
>
> Btw, why the default value of this setting is 10, instead of -1 ?
I don't know. I guess just by historical reason, for this variable
has been existed before support of -1 is added.
^ permalink raw reply
* [dpdk-dev] [PATCH v7 3/6] raw/ntb: add handshake process
From: Xiaoyun Li @ 2019-06-20 10:21 UTC (permalink / raw)
To: jingjing.wu, keith.wiles, cunming.liang, omkar.maslekar; +Cc: dev, Xiaoyun Li
In-Reply-To: <20190620102147.41557-1-xiaoyun.li@intel.com>
Add handshake process using doorbell so that two hosts can
communicate to start and stop.
Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
---
drivers/raw/ntb_rawdev/ntb_rawdev.c | 336 +++++++++++++++++++++++++++-
1 file changed, 335 insertions(+), 1 deletion(-)
diff --git a/drivers/raw/ntb_rawdev/ntb_rawdev.c b/drivers/raw/ntb_rawdev/ntb_rawdev.c
index 113ef0169..e4ae95a01 100644
--- a/drivers/raw/ntb_rawdev/ntb_rawdev.c
+++ b/drivers/raw/ntb_rawdev/ntb_rawdev.c
@@ -28,6 +28,183 @@ static const struct rte_pci_id pci_id_ntb_map[] = {
{ .vendor_id = 0, /* sentinel */ },
};
+static int
+ntb_set_mw(struct rte_rawdev *dev, int mw_idx, uint64_t mw_size)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ char mw_name[RTE_MEMZONE_NAMESIZE];
+ const struct rte_memzone *mz;
+ int ret = 0;
+
+ if (hw->ntb_ops->mw_set_trans == NULL) {
+ NTB_LOG(ERR, "Not supported to set mw.");
+ return -ENOTSUP;
+ }
+
+ snprintf(mw_name, sizeof(mw_name), "ntb_%d_mw_%d",
+ dev->dev_id, mw_idx);
+
+ mz = rte_memzone_lookup(mw_name);
+ if (mz)
+ return 0;
+
+ /**
+ * Hardware requires that mapped memory base address should be
+ * aligned with EMBARSZ and needs continuous memzone.
+ */
+ mz = rte_memzone_reserve_aligned(mw_name, mw_size, dev->socket_id,
+ RTE_MEMZONE_IOVA_CONTIG, hw->mw_size[mw_idx]);
+ if (!mz) {
+ NTB_LOG(ERR, "Cannot allocate aligned memzone.");
+ return -EIO;
+ }
+ hw->mz[mw_idx] = mz;
+
+ ret = (*hw->ntb_ops->mw_set_trans)(dev, mw_idx, mz->iova, mw_size);
+ if (ret) {
+ NTB_LOG(ERR, "Cannot set mw translation.");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void
+ntb_link_cleanup(struct rte_rawdev *dev)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ int status, i;
+
+ if (hw->ntb_ops->spad_write == NULL ||
+ hw->ntb_ops->mw_set_trans == NULL) {
+ NTB_LOG(ERR, "Not supported to clean up link.");
+ return;
+ }
+
+ /* Clean spad registers. */
+ for (i = 0; i < hw->spad_cnt; i++) {
+ status = (*hw->ntb_ops->spad_write)(dev, i, 0, 0);
+ if (status)
+ NTB_LOG(ERR, "Failed to clean local spad.");
+ }
+
+ /* Clear mw so that peer cannot access local memory.*/
+ for (i = 0; i < hw->mw_cnt; i++) {
+ status = (*hw->ntb_ops->mw_set_trans)(dev, i, 0, 0);
+ if (status)
+ NTB_LOG(ERR, "Failed to clean mw.");
+ }
+}
+
+static void
+ntb_dev_intr_handler(void *param)
+{
+ struct rte_rawdev *dev = (struct rte_rawdev *)param;
+ struct ntb_hw *hw = dev->dev_private;
+ uint32_t mw_size_h, mw_size_l;
+ uint64_t db_bits = 0;
+ int i = 0;
+
+ if (hw->ntb_ops->db_read == NULL ||
+ hw->ntb_ops->db_clear == NULL ||
+ hw->ntb_ops->peer_db_set == NULL) {
+ NTB_LOG(ERR, "Doorbell is not supported.");
+ return;
+ }
+
+ db_bits = (*hw->ntb_ops->db_read)(dev);
+ if (!db_bits)
+ NTB_LOG(ERR, "No doorbells");
+
+ /* Doorbell 0 is for peer device ready. */
+ if (db_bits & 1) {
+ NTB_LOG(DEBUG, "DB0: Peer device is up.");
+ /* Clear received doorbell. */
+ (*hw->ntb_ops->db_clear)(dev, 1);
+
+ /**
+ * Peer dev is already up. All mw settings are already done.
+ * Skip them.
+ */
+ if (hw->peer_dev_up)
+ return;
+
+ if (hw->ntb_ops->spad_read == NULL ||
+ hw->ntb_ops->spad_write == NULL) {
+ NTB_LOG(ERR, "Scratchpad is not supported.");
+ return;
+ }
+
+ hw->peer_mw_cnt = (*hw->ntb_ops->spad_read)
+ (dev, SPAD_NUM_MWS, 0);
+ hw->peer_mw_size = rte_zmalloc("uint64_t",
+ hw->peer_mw_cnt * sizeof(uint64_t), 0);
+ for (i = 0; i < hw->mw_cnt; i++) {
+ mw_size_h = (*hw->ntb_ops->spad_read)
+ (dev, SPAD_MW0_SZ_H + 2 * i, 0);
+ mw_size_l = (*hw->ntb_ops->spad_read)
+ (dev, SPAD_MW0_SZ_L + 2 * i, 0);
+ hw->peer_mw_size[i] = ((uint64_t)mw_size_h << 32) |
+ mw_size_l;
+ NTB_LOG(DEBUG, "Peer %u mw size: 0x%"PRIx64"", i,
+ hw->peer_mw_size[i]);
+ }
+
+ hw->peer_dev_up = 1;
+
+ /**
+ * Handshake with peer. Spad_write only works when both
+ * devices are up. So write spad again when db is received.
+ * And set db again for the later device who may miss
+ * the 1st db.
+ */
+ for (i = 0; i < hw->mw_cnt; i++) {
+ (*hw->ntb_ops->spad_write)(dev, SPAD_NUM_MWS,
+ 1, hw->mw_cnt);
+ mw_size_h = hw->mw_size[i] >> 32;
+ (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_SZ_H + 2 * i,
+ 1, mw_size_h);
+
+ mw_size_l = hw->mw_size[i];
+ (*hw->ntb_ops->spad_write)(dev, SPAD_MW0_SZ_L + 2 * i,
+ 1, mw_size_l);
+ }
+ (*hw->ntb_ops->peer_db_set)(dev, 0);
+
+ /* To get the link info. */
+ if (hw->ntb_ops->get_link_status == NULL) {
+ NTB_LOG(ERR, "Not supported to get link status.");
+ return;
+ }
+ (*hw->ntb_ops->get_link_status)(dev);
+ NTB_LOG(INFO, "Link is up. Link speed: %u. Link width: %u",
+ hw->link_speed, hw->link_width);
+ return;
+ }
+
+ if (db_bits & (1 << 1)) {
+ NTB_LOG(DEBUG, "DB1: Peer device is down.");
+ /* Clear received doorbell. */
+ (*hw->ntb_ops->db_clear)(dev, 2);
+
+ /* Peer device will be down, So clean local side too. */
+ ntb_link_cleanup(dev);
+
+ hw->peer_dev_up = 0;
+ /* Response peer's dev_stop request. */
+ (*hw->ntb_ops->peer_db_set)(dev, 2);
+ return;
+ }
+
+ if (db_bits & (1 << 2)) {
+ NTB_LOG(DEBUG, "DB2: Peer device agrees dev to be down.");
+ /* Clear received doorbell. */
+ (*hw->ntb_ops->db_clear)(dev, (1 << 2));
+ hw->peer_dev_up = 0;
+ return;
+ }
+}
+
static void
ntb_queue_conf_get(struct rte_rawdev *dev __rte_unused,
uint16_t queue_id __rte_unused,
@@ -147,7 +324,22 @@ ntb_dev_configure(const struct rte_rawdev *dev __rte_unused,
static int
ntb_dev_start(struct rte_rawdev *dev)
{
+ struct ntb_hw *hw = dev->dev_private;
+ int ret, i;
+
/* TODO: init queues and start queues. */
+
+ /* Map memory of bar_size to remote. */
+ hw->mz = rte_zmalloc("struct rte_memzone *",
+ hw->mw_cnt * sizeof(struct rte_memzone *), 0);
+ for (i = 0; i < hw->mw_cnt; i++) {
+ ret = ntb_set_mw(dev, i, hw->mw_size[i]);
+ if (ret) {
+ NTB_LOG(ERR, "Fail to set mw.");
+ return ret;
+ }
+ }
+
dev->started = 1;
return 0;
@@ -156,13 +348,59 @@ ntb_dev_start(struct rte_rawdev *dev)
static void
ntb_dev_stop(struct rte_rawdev *dev)
{
+ struct ntb_hw *hw = dev->dev_private;
+ uint32_t time_out;
+ int status;
+
/* TODO: stop rx/tx queues. */
+
+ if (!hw->peer_dev_up)
+ goto clean;
+
+ ntb_link_cleanup(dev);
+
+ /* Notify the peer that device will be down. */
+ if (hw->ntb_ops->peer_db_set == NULL) {
+ NTB_LOG(ERR, "Peer doorbell setting is not supported.");
+ return;
+ }
+ status = (*hw->ntb_ops->peer_db_set)(dev, 1);
+ if (status) {
+ NTB_LOG(ERR, "Failed to tell peer device is down.");
+ return;
+ }
+
+ /*
+ * Set time out as 1s in case that the peer is stopped accidently
+ * without any notification.
+ */
+ time_out = 1000000;
+
+ /* Wait for cleanup work down before db mask clear. */
+ while (hw->peer_dev_up && time_out) {
+ time_out -= 10;
+ rte_delay_us(10);
+ }
+
+clean:
+ /* Clear doorbells mask. */
+ if (hw->ntb_ops->db_set_mask == NULL) {
+ NTB_LOG(ERR, "Doorbell mask setting is not supported.");
+ return;
+ }
+ status = (*hw->ntb_ops->db_set_mask)(dev,
+ (((uint64_t)1 << hw->db_cnt) - 1));
+ if (status)
+ NTB_LOG(ERR, "Failed to clear doorbells.");
+
dev->started = 0;
}
static int
ntb_dev_close(struct rte_rawdev *dev)
{
+ struct ntb_hw *hw = dev->dev_private;
+ struct rte_intr_handle *intr_handle;
int ret = 0;
if (dev->started)
@@ -170,6 +408,20 @@ ntb_dev_close(struct rte_rawdev *dev)
/* TODO: free queues. */
+ intr_handle = &hw->pci_dev->intr_handle;
+ /* Clean datapath event and vec mapping */
+ rte_intr_efd_disable(intr_handle);
+ if (intr_handle->intr_vec) {
+ rte_free(intr_handle->intr_vec);
+ intr_handle->intr_vec = NULL;
+ }
+ /* Disable uio intr before callback unregister */
+ rte_intr_disable(intr_handle);
+
+ /* Unregister callback func to eal lib */
+ rte_intr_callback_unregister(intr_handle,
+ ntb_dev_intr_handler, dev);
+
return ret;
}
@@ -346,7 +598,9 @@ static int
ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev)
{
struct ntb_hw *hw = dev->dev_private;
- int ret;
+ struct rte_intr_handle *intr_handle;
+ uint32_t val;
+ int ret, i;
hw->pci_dev = pci_dev;
hw->peer_dev_up = 0;
@@ -377,6 +631,86 @@ ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev)
if (ret)
return ret;
+ /* Init doorbell. */
+ hw->db_valid_mask = RTE_LEN2MASK(hw->db_cnt, uint64_t);
+
+ intr_handle = &pci_dev->intr_handle;
+ /* Register callback func to eal lib */
+ rte_intr_callback_register(intr_handle,
+ ntb_dev_intr_handler, dev);
+
+ ret = rte_intr_efd_enable(intr_handle, hw->db_cnt);
+ if (ret)
+ return ret;
+
+ /* To clarify, the interrupt for each doorbell is already mapped
+ * by default for intel gen3. They are mapped to msix vec 1-32,
+ * and hardware intr is mapped to 0. Map all to 0 for uio.
+ */
+ if (!rte_intr_cap_multiple(intr_handle)) {
+ for (i = 0; i < hw->db_cnt; i++) {
+ if (hw->ntb_ops->vector_bind == NULL)
+ return -ENOTSUP;
+ ret = (*hw->ntb_ops->vector_bind)(dev, i, 0);
+ if (ret)
+ return ret;
+ }
+ }
+
+ if (hw->ntb_ops->db_set_mask == NULL ||
+ hw->ntb_ops->peer_db_set == NULL) {
+ NTB_LOG(ERR, "Doorbell is not supported.");
+ return -ENOTSUP;
+ }
+ hw->db_mask = 0;
+ ret = (*hw->ntb_ops->db_set_mask)(dev, hw->db_mask);
+ if (ret) {
+ NTB_LOG(ERR, "Unanle to enable intr for all dbs.");
+ return ret;
+ }
+
+ /* enable uio intr after callback register */
+ rte_intr_enable(intr_handle);
+
+ if (hw->ntb_ops->spad_write == NULL) {
+ NTB_LOG(ERR, "Scratchpad is not supported.");
+ return -ENOTSUP;
+ }
+ /* Tell peer the mw_cnt of local side. */
+ ret = (*hw->ntb_ops->spad_write)(dev, SPAD_NUM_MWS, 1, hw->mw_cnt);
+ if (ret) {
+ NTB_LOG(ERR, "Failed to tell peer mw count.");
+ return ret;
+ }
+
+ /* Tell peer each mw size on local side. */
+ for (i = 0; i < hw->mw_cnt; i++) {
+ NTB_LOG(DEBUG, "Local %u mw size: 0x%"PRIx64"", i,
+ hw->mw_size[i]);
+ val = hw->mw_size[i] >> 32;
+ ret = (*hw->ntb_ops->spad_write)
+ (dev, SPAD_MW0_SZ_H + 2 * i, 1, val);
+ if (ret) {
+ NTB_LOG(ERR, "Failed to tell peer mw size.");
+ return ret;
+ }
+
+ val = hw->mw_size[i];
+ ret = (*hw->ntb_ops->spad_write)
+ (dev, SPAD_MW0_SZ_L + 2 * i, 1, val);
+ if (ret) {
+ NTB_LOG(ERR, "Failed to tell peer mw size.");
+ return ret;
+ }
+ }
+
+ /* Ring doorbell 0 to tell peer the device is ready. */
+ ret = (*hw->ntb_ops->peer_db_set)(dev, 0);
+ if (ret) {
+ NTB_LOG(ERR, "Failed to tell peer device is probed.");
+ return ret;
+ }
+
return ret;
}
--
2.17.1
^ permalink raw reply related
* [dpdk-dev] [PATCH v7 2/6] raw/ntb: add intel ntb support
From: Xiaoyun Li @ 2019-06-20 10:21 UTC (permalink / raw)
To: jingjing.wu, keith.wiles, cunming.liang, omkar.maslekar; +Cc: dev, Xiaoyun Li
In-Reply-To: <20190620102147.41557-1-xiaoyun.li@intel.com>
Add in the list of registers for the device. And enable ntb device
ops for intel skylake platform.
Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
---
drivers/raw/ntb_rawdev/Makefile | 1 +
drivers/raw/ntb_rawdev/meson.build | 3 +-
drivers/raw/ntb_rawdev/ntb_hw_intel.c | 369 ++++++++++++++++++++++++++
drivers/raw/ntb_rawdev/ntb_hw_intel.h | 86 ++++++
drivers/raw/ntb_rawdev/ntb_rawdev.c | 5 +
5 files changed, 463 insertions(+), 1 deletion(-)
create mode 100644 drivers/raw/ntb_rawdev/ntb_hw_intel.c
create mode 100644 drivers/raw/ntb_rawdev/ntb_hw_intel.h
diff --git a/drivers/raw/ntb_rawdev/Makefile b/drivers/raw/ntb_rawdev/Makefile
index da87a4610..74c045a86 100644
--- a/drivers/raw/ntb_rawdev/Makefile
+++ b/drivers/raw/ntb_rawdev/Makefile
@@ -23,5 +23,6 @@ LIBABIVER := 1
# all source are stored in SRCS-y
#
SRCS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += ntb_rawdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += ntb_hw_intel.c
include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/raw/ntb_rawdev/meson.build b/drivers/raw/ntb_rawdev/meson.build
index ca905049d..c696f60b3 100644
--- a/drivers/raw/ntb_rawdev/meson.build
+++ b/drivers/raw/ntb_rawdev/meson.build
@@ -3,5 +3,6 @@
deps += ['rawdev', 'mbuf', 'mempool',
'pci', 'bus_pci']
-sources = files('ntb_rawdev.c')
+sources = files('ntb_rawdev.c',
+ 'ntb_hw_intel.c')
allow_experimental_apis = true
diff --git a/drivers/raw/ntb_rawdev/ntb_hw_intel.c b/drivers/raw/ntb_rawdev/ntb_hw_intel.c
new file mode 100644
index 000000000..1185cd189
--- /dev/null
+++ b/drivers/raw/ntb_rawdev/ntb_hw_intel.c
@@ -0,0 +1,369 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <rte_io.h>
+#include <rte_eal.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_rawdev.h>
+#include <rte_rawdev_pmd.h>
+
+#include "ntb_rawdev.h"
+#include "ntb_hw_intel.h"
+
+enum xeon_ntb_bar {
+ XEON_NTB_BAR23 = 2,
+ XEON_NTB_BAR45 = 4,
+};
+
+static enum xeon_ntb_bar intel_ntb_bar[] = {
+ XEON_NTB_BAR23,
+ XEON_NTB_BAR45,
+};
+
+static int
+intel_ntb_dev_init(struct rte_rawdev *dev)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint8_t reg_val, bar;
+ int ret, i;
+
+ if (hw == NULL) {
+ NTB_LOG(ERR, "Invalid device.");
+ return -EINVAL;
+ }
+
+ ret = rte_pci_read_config(hw->pci_dev, ®_val,
+ sizeof(reg_val), XEON_PPD_OFFSET);
+ if (ret < 0) {
+ NTB_LOG(ERR, "Cannot get NTB PPD (PCIe port definition).");
+ return -EIO;
+ }
+
+ /* Check connection topo type. Only support B2B. */
+ switch (reg_val & XEON_PPD_CONN_MASK) {
+ case XEON_PPD_CONN_B2B:
+ NTB_LOG(INFO, "Topo B2B (back to back) is using.");
+ break;
+ case XEON_PPD_CONN_TRANSPARENT:
+ case XEON_PPD_CONN_RP:
+ NTB_LOG(ERR, "Not supported conn topo. Please use B2B.");
+ return -EINVAL;
+ }
+
+ /* Check device type. */
+ if (reg_val & XEON_PPD_DEV_DSD) {
+ NTB_LOG(INFO, "DSD, Downstream Device.");
+ hw->topo = NTB_TOPO_B2B_DSD;
+ } else {
+ NTB_LOG(INFO, "USD, Upstream device.");
+ hw->topo = NTB_TOPO_B2B_USD;
+ }
+
+ /* Check if bar4 is split. Do not support split bar. */
+ if (reg_val & XEON_PPD_SPLIT_BAR_MASK) {
+ NTB_LOG(ERR, "Do not support split bar.");
+ return -EINVAL;
+ }
+
+ hw->hw_addr = (char *)hw->pci_dev->mem_resource[0].addr;
+
+ hw->mw_cnt = XEON_MW_COUNT;
+ hw->db_cnt = XEON_DB_COUNT;
+ hw->spad_cnt = XEON_SPAD_COUNT;
+
+ hw->mw_size = rte_zmalloc("uint64_t",
+ hw->mw_cnt * sizeof(uint64_t), 0);
+ for (i = 0; i < hw->mw_cnt; i++) {
+ bar = intel_ntb_bar[i];
+ hw->mw_size[i] = hw->pci_dev->mem_resource[bar].len;
+ }
+
+ /* Reserve the last 2 spad registers for users. */
+ for (i = 0; i < NTB_SPAD_USER_MAX_NUM; i++) {
+ hw->spad_user_list[i] = hw->spad_cnt;
+ }
+ hw->spad_user_list[0] = hw->spad_cnt - 2;
+ hw->spad_user_list[1] = hw->spad_cnt - 1;
+
+ return 0;
+}
+
+static void *
+intel_ntb_get_peer_mw_addr(struct rte_rawdev *dev, int mw_idx)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint8_t bar;
+
+ if (hw == NULL) {
+ NTB_LOG(ERR, "Invalid device.");
+ return 0;
+ }
+
+ if (mw_idx < 0 || mw_idx >= hw->mw_cnt) {
+ NTB_LOG(ERR, "Invalid memory window index (0 - %u).",
+ hw->mw_cnt - 1);
+ return 0;
+ }
+
+ bar = intel_ntb_bar[mw_idx];
+
+ return hw->pci_dev->mem_resource[bar].addr;
+}
+
+static int
+intel_ntb_mw_set_trans(struct rte_rawdev *dev, int mw_idx,
+ uint64_t addr, uint64_t size)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ void *xlat_addr, *limit_addr;
+ uint64_t xlat_off, limit_off;
+ uint64_t base, limit;
+ uint8_t bar;
+
+ if (hw == NULL) {
+ NTB_LOG(ERR, "Invalid device.");
+ return -EINVAL;
+ }
+
+ if (mw_idx < 0 || mw_idx >= hw->mw_cnt) {
+ NTB_LOG(ERR, "Invalid memory window index (0 - %u).",
+ hw->mw_cnt - 1);
+ return -EINVAL;
+ }
+
+ bar = intel_ntb_bar[mw_idx];
+
+ xlat_off = XEON_IMBAR1XBASE_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET;
+ limit_off = XEON_IMBAR1XLMT_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET;
+ xlat_addr = hw->hw_addr + xlat_off;
+ limit_addr = hw->hw_addr + limit_off;
+
+ /* Limit reg val should be EMBAR base address plus MW size. */
+ base = addr;
+ limit = hw->pci_dev->mem_resource[bar].phys_addr + size;
+ rte_write64(base, xlat_addr);
+ rte_write64(limit, limit_addr);
+
+ /* Setup the external point so that remote can access. */
+ xlat_off = XEON_EMBAR1_OFFSET + 8 * mw_idx;
+ xlat_addr = hw->hw_addr + xlat_off;
+ limit_off = XEON_EMBAR1XLMT_OFFSET + mw_idx * XEON_BAR_INTERVAL_OFFSET;
+ limit_addr = hw->hw_addr + limit_off;
+ base = rte_read64(xlat_addr);
+ base &= ~0xf;
+ limit = base + size;
+ rte_write64(limit, limit_addr);
+
+ return 0;
+}
+
+static int
+intel_ntb_get_link_status(struct rte_rawdev *dev)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint16_t reg_val;
+ int ret;
+
+ if (hw == NULL) {
+ NTB_LOG(ERR, "Invalid device.");
+ return -EINVAL;
+ }
+
+ ret = rte_pci_read_config(hw->pci_dev, ®_val,
+ sizeof(reg_val), XEON_LINK_STATUS_OFFSET);
+ if (ret < 0) {
+ NTB_LOG(ERR, "Unable to get link status.");
+ return -EIO;
+ }
+
+ hw->link_status = NTB_LNK_STA_ACTIVE(reg_val);
+
+ if (hw->link_status) {
+ hw->link_speed = NTB_LNK_STA_SPEED(reg_val);
+ hw->link_width = NTB_LNK_STA_WIDTH(reg_val);
+ } else {
+ hw->link_speed = NTB_SPEED_NONE;
+ hw->link_width = NTB_WIDTH_NONE;
+ }
+
+ return 0;
+}
+
+static int
+intel_ntb_set_link(struct rte_rawdev *dev, bool up)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint32_t ntb_ctrl, reg_off;
+ void *reg_addr;
+
+ reg_off = XEON_NTBCNTL_OFFSET;
+ reg_addr = hw->hw_addr + reg_off;
+ ntb_ctrl = rte_read32(reg_addr);
+
+ if (up) {
+ ntb_ctrl &= ~(NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK);
+ ntb_ctrl |= NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP;
+ ntb_ctrl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP;
+ } else {
+ ntb_ctrl &= ~(NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP);
+ ntb_ctrl &= ~(NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP);
+ ntb_ctrl |= NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK;
+ }
+
+ rte_write32(ntb_ctrl, reg_addr);
+
+ return 0;
+}
+
+static uint32_t
+intel_ntb_spad_read(struct rte_rawdev *dev, int spad, bool peer)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint32_t spad_v, reg_off;
+ void *reg_addr;
+
+ if (spad < 0 || spad >= hw->spad_cnt) {
+ NTB_LOG(ERR, "Invalid spad reg index.");
+ return 0;
+ }
+
+ /* When peer is true, read peer spad reg */
+ reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET;
+ reg_addr = hw->hw_addr + reg_off + (spad << 2);
+ spad_v = rte_read32(reg_addr);
+
+ return spad_v;
+}
+
+static int
+intel_ntb_spad_write(struct rte_rawdev *dev, int spad,
+ bool peer, uint32_t spad_v)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint32_t reg_off;
+ void *reg_addr;
+
+ if (spad < 0 || spad >= hw->spad_cnt) {
+ NTB_LOG(ERR, "Invalid spad reg index.");
+ return -EINVAL;
+ }
+
+ /* When peer is true, write peer spad reg */
+ reg_off = peer ? XEON_B2B_SPAD_OFFSET : XEON_IM_SPAD_OFFSET;
+ reg_addr = hw->hw_addr + reg_off + (spad << 2);
+
+ rte_write32(spad_v, reg_addr);
+
+ return 0;
+}
+
+static uint64_t
+intel_ntb_db_read(struct rte_rawdev *dev)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint64_t db_off, db_bits;
+ void *db_addr;
+
+ db_off = XEON_IM_INT_STATUS_OFFSET;
+ db_addr = hw->hw_addr + db_off;
+
+ db_bits = rte_read64(db_addr);
+
+ return db_bits;
+}
+
+static int
+intel_ntb_db_clear(struct rte_rawdev *dev, uint64_t db_bits)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint64_t db_off;
+ void *db_addr;
+
+ db_off = XEON_IM_INT_STATUS_OFFSET;
+ db_addr = hw->hw_addr + db_off;
+
+ rte_write64(db_bits, db_addr);
+
+ return 0;
+}
+
+static int
+intel_ntb_db_set_mask(struct rte_rawdev *dev, uint64_t db_mask)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint64_t db_m_off;
+ void *db_m_addr;
+
+ db_m_off = XEON_IM_INT_DISABLE_OFFSET;
+ db_m_addr = hw->hw_addr + db_m_off;
+
+ db_mask |= hw->db_mask;
+
+ rte_write64(db_mask, db_m_addr);
+
+ hw->db_mask = db_mask;
+
+ return 0;
+}
+
+static int
+intel_ntb_peer_db_set(struct rte_rawdev *dev, uint8_t db_idx)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint32_t db_off;
+ void *db_addr;
+
+ if (((uint64_t)1 << db_idx) & ~hw->db_valid_mask) {
+ NTB_LOG(ERR, "Invalid doorbell.");
+ return -EINVAL;
+ }
+
+ db_off = XEON_IM_DOORBELL_OFFSET + db_idx * 4;
+ db_addr = hw->hw_addr + db_off;
+
+ rte_write32(1, db_addr);
+
+ return 0;
+}
+
+static int
+intel_ntb_vector_bind(struct rte_rawdev *dev, uint8_t intr, uint8_t msix)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ uint8_t reg_off;
+ void *reg_addr;
+
+ if (intr >= hw->db_cnt) {
+ NTB_LOG(ERR, "Invalid intr source.");
+ return -EINVAL;
+ }
+
+ /* Bind intr source to msix vector */
+ reg_off = XEON_INTVEC_OFFSET;
+ reg_addr = hw->hw_addr + reg_off + intr;
+
+ rte_write8(msix, reg_addr);
+
+ return 0;
+}
+
+/* operations for primary side of local ntb */
+const struct ntb_dev_ops intel_ntb_ops = {
+ .ntb_dev_init = intel_ntb_dev_init,
+ .get_peer_mw_addr = intel_ntb_get_peer_mw_addr,
+ .mw_set_trans = intel_ntb_mw_set_trans,
+ .get_link_status = intel_ntb_get_link_status,
+ .set_link = intel_ntb_set_link,
+ .spad_read = intel_ntb_spad_read,
+ .spad_write = intel_ntb_spad_write,
+ .db_read = intel_ntb_db_read,
+ .db_clear = intel_ntb_db_clear,
+ .db_set_mask = intel_ntb_db_set_mask,
+ .peer_db_set = intel_ntb_peer_db_set,
+ .vector_bind = intel_ntb_vector_bind,
+};
diff --git a/drivers/raw/ntb_rawdev/ntb_hw_intel.h b/drivers/raw/ntb_rawdev/ntb_hw_intel.h
new file mode 100644
index 000000000..4d1e64504
--- /dev/null
+++ b/drivers/raw/ntb_rawdev/ntb_hw_intel.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation.
+ */
+
+#ifndef _NTB_HW_INTEL_H_
+#define _NTB_HW_INTEL_H_
+
+/* Ntb control and link status */
+#define NTB_CTL_CFG_LOCK 1
+#define NTB_CTL_DISABLE 2
+#define NTB_CTL_S2P_BAR2_SNOOP (1 << 2)
+#define NTB_CTL_P2S_BAR2_SNOOP (1 << 4)
+#define NTB_CTL_S2P_BAR4_SNOOP (1 << 6)
+#define NTB_CTL_P2S_BAR4_SNOOP (1 << 8)
+#define NTB_CTL_S2P_BAR5_SNOOP (1 << 12)
+#define NTB_CTL_P2S_BAR5_SNOOP (1 << 14)
+
+#define NTB_LNK_STA_ACTIVE_BIT 0x2000
+#define NTB_LNK_STA_SPEED_MASK 0x000f
+#define NTB_LNK_STA_WIDTH_MASK 0x03f0
+#define NTB_LNK_STA_ACTIVE(x) (!!((x) & NTB_LNK_STA_ACTIVE_BIT))
+#define NTB_LNK_STA_SPEED(x) ((x) & NTB_LNK_STA_SPEED_MASK)
+#define NTB_LNK_STA_WIDTH(x) (((x) & NTB_LNK_STA_WIDTH_MASK) >> 4)
+
+/* Intel Skylake Xeon hardware */
+#define XEON_IMBAR1SZ_OFFSET 0x00d0
+#define XEON_IMBAR2SZ_OFFSET 0x00d1
+#define XEON_EMBAR1SZ_OFFSET 0x00d2
+#define XEON_EMBAR2SZ_OFFSET 0x00d3
+#define XEON_DEVCTRL_OFFSET 0x0098
+#define XEON_DEVSTS_OFFSET 0x009a
+#define XEON_UNCERRSTS_OFFSET 0x014c
+#define XEON_CORERRSTS_OFFSET 0x0158
+#define XEON_LINK_STATUS_OFFSET 0x01a2
+
+#define XEON_NTBCNTL_OFFSET 0x0000
+#define XEON_BAR_INTERVAL_OFFSET 0x0010
+#define XEON_IMBAR1XBASE_OFFSET 0x0010 /* SBAR2XLAT */
+#define XEON_IMBAR1XLMT_OFFSET 0x0018 /* SBAR2LMT */
+#define XEON_IMBAR2XBASE_OFFSET 0x0020 /* SBAR4XLAT */
+#define XEON_IMBAR2XLMT_OFFSET 0x0028 /* SBAR4LMT */
+#define XEON_IM_INT_STATUS_OFFSET 0x0040
+#define XEON_IM_INT_DISABLE_OFFSET 0x0048
+#define XEON_IM_SPAD_OFFSET 0x0080 /* SPAD */
+#define XEON_USMEMMISS_OFFSET 0x0070
+#define XEON_INTVEC_OFFSET 0x00d0
+#define XEON_IM_DOORBELL_OFFSET 0x0100 /* SDOORBELL0 */
+#define XEON_B2B_SPAD_OFFSET 0x0180 /* B2B SPAD */
+#define XEON_EMBAR0XBASE_OFFSET 0x4008 /* B2B_XLAT */
+#define XEON_EMBAR1XBASE_OFFSET 0x4010 /* PBAR2XLAT */
+#define XEON_EMBAR1XLMT_OFFSET 0x4018 /* PBAR2LMT */
+#define XEON_EMBAR2XBASE_OFFSET 0x4020 /* PBAR4XLAT */
+#define XEON_EMBAR2XLMT_OFFSET 0x4028 /* PBAR4LMT */
+#define XEON_EM_INT_STATUS_OFFSET 0x4040
+#define XEON_EM_INT_DISABLE_OFFSET 0x4048
+#define XEON_EM_SPAD_OFFSET 0x4080 /* remote SPAD */
+#define XEON_EM_DOORBELL_OFFSET 0x4100 /* PDOORBELL0 */
+#define XEON_SPCICMD_OFFSET 0x4504 /* SPCICMD */
+#define XEON_EMBAR0_OFFSET 0x4510 /* SBAR0BASE */
+#define XEON_EMBAR1_OFFSET 0x4518 /* SBAR23BASE */
+#define XEON_EMBAR2_OFFSET 0x4520 /* SBAR45BASE */
+
+#define XEON_PPD_OFFSET 0x00d4
+#define XEON_PPD_CONN_MASK 0x03
+#define XEON_PPD_CONN_TRANSPARENT 0x00
+#define XEON_PPD_CONN_B2B 0x01
+#define XEON_PPD_CONN_RP 0x02
+#define XEON_PPD_DEV_MASK 0x10
+#define XEON_PPD_DEV_USD 0x00
+#define XEON_PPD_DEV_DSD 0x10
+#define XEON_PPD_SPLIT_BAR_MASK 0x40
+
+
+#define XEON_MW_COUNT 2
+
+#define XEON_DB_COUNT 32
+#define XEON_DB_LINK 32
+#define XEON_DB_LINK_BIT (1ULL << XEON_DB_LINK)
+#define XEON_DB_MSIX_VECTOR_COUNT 33
+#define XEON_DB_MSIX_VECTOR_SHIFT 1
+#define XEON_DB_TOTAL_SHIFT 33
+#define XEON_SPAD_COUNT 16
+
+extern const struct ntb_dev_ops intel_ntb_ops;
+
+#endif /* _NTB_HW_INTEL_H_ */
diff --git a/drivers/raw/ntb_rawdev/ntb_rawdev.c b/drivers/raw/ntb_rawdev/ntb_rawdev.c
index 07ad81d44..113ef0169 100644
--- a/drivers/raw/ntb_rawdev/ntb_rawdev.c
+++ b/drivers/raw/ntb_rawdev/ntb_rawdev.c
@@ -18,11 +18,13 @@
#include <rte_rawdev.h>
#include <rte_rawdev_pmd.h>
+#include "ntb_hw_intel.h"
#include "ntb_rawdev.h"
int ntb_logtype;
static const struct rte_pci_id pci_id_ntb_map[] = {
+ { RTE_PCI_DEVICE(NTB_INTEL_VENDOR_ID, NTB_INTEL_DEV_ID_B2B_SKX) },
{ .vendor_id = 0, /* sentinel */ },
};
@@ -353,6 +355,9 @@ ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev)
hw->link_width = NTB_WIDTH_NONE;
switch (pci_dev->id.device_id) {
+ case NTB_INTEL_DEV_ID_B2B_SKX:
+ hw->ntb_ops = &intel_ntb_ops;
+ break;
default:
NTB_LOG(ERR, "Not supported device.");
return -EINVAL;
--
2.17.1
^ permalink raw reply related
* [dpdk-dev] [PATCH v7 1/6] raw/ntb: introduce ntb rawdev driver
From: Xiaoyun Li @ 2019-06-20 10:21 UTC (permalink / raw)
To: jingjing.wu, keith.wiles, cunming.liang, omkar.maslekar; +Cc: dev, Xiaoyun Li
In-Reply-To: <20190620102147.41557-1-xiaoyun.li@intel.com>
Introduce rawdev driver support for NTB (Non-transparent Bridge) which
can help to connect two separate hosts with each other.
Signed-off-by: Xiaoyun Li <xiaoyun.li@intel.com>
---
config/common_base | 5 +
drivers/raw/Makefile | 1 +
drivers/raw/meson.build | 2 +-
drivers/raw/ntb_rawdev/Makefile | 27 +
drivers/raw/ntb_rawdev/meson.build | 7 +
drivers/raw/ntb_rawdev/ntb_rawdev.c | 488 ++++++++++++++++++
drivers/raw/ntb_rawdev/ntb_rawdev.h | 164 ++++++
.../ntb_rawdev/rte_pmd_ntb_rawdev_version.map | 4 +
mk/rte.app.mk | 1 +
9 files changed, 698 insertions(+), 1 deletion(-)
create mode 100644 drivers/raw/ntb_rawdev/Makefile
create mode 100644 drivers/raw/ntb_rawdev/meson.build
create mode 100644 drivers/raw/ntb_rawdev/ntb_rawdev.c
create mode 100644 drivers/raw/ntb_rawdev/ntb_rawdev.h
create mode 100644 drivers/raw/ntb_rawdev/rte_pmd_ntb_rawdev_version.map
diff --git a/config/common_base b/config/common_base
index 5cb73a7a8..d18dae7b0 100644
--- a/config/common_base
+++ b/config/common_base
@@ -747,6 +747,11 @@ CONFIG_RTE_LIBRTE_PMD_DPAA2_QDMA_RAWDEV=n
#
CONFIG_RTE_LIBRTE_PMD_IFPGA_RAWDEV=y
+#
+# Compile PMD for NTB raw device
+#
+CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV=y
+
#
# Compile librte_ring
#
diff --git a/drivers/raw/Makefile b/drivers/raw/Makefile
index 8e29b4a56..efe61f451 100644
--- a/drivers/raw/Makefile
+++ b/drivers/raw/Makefile
@@ -10,5 +10,6 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_DPAA2_CMDIF_RAWDEV) += dpaa2_cmdif
DIRS-$(CONFIG_RTE_LIBRTE_PMD_DPAA2_QDMA_RAWDEV) += dpaa2_qdma
endif
DIRS-$(CONFIG_RTE_LIBRTE_PMD_IFPGA_RAWDEV) += ifpga_rawdev
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += ntb_rawdev
include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/drivers/raw/meson.build b/drivers/raw/meson.build
index a61cdccef..6abf659d0 100644
--- a/drivers/raw/meson.build
+++ b/drivers/raw/meson.build
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright 2018 NXP
-drivers = ['skeleton_rawdev', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga_rawdev']
+drivers = ['skeleton_rawdev', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga_rawdev', 'ntb_rawdev']
std_deps = ['rawdev']
config_flag_fmt = 'RTE_LIBRTE_PMD_@0@_RAWDEV'
driver_name_fmt = 'rte_pmd_@0@'
diff --git a/drivers/raw/ntb_rawdev/Makefile b/drivers/raw/ntb_rawdev/Makefile
new file mode 100644
index 000000000..da87a4610
--- /dev/null
+++ b/drivers/raw/ntb_rawdev/Makefile
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_ntb_rawdev.a
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool
+LDLIBS += -lrte_pci -lrte_bus_pci
+LDLIBS += -lrte_rawdev
+
+EXPORT_MAP := rte_pmd_ntb_rawdev_version.map
+
+LIBABIVER := 1
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += ntb_rawdev.c
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/raw/ntb_rawdev/meson.build b/drivers/raw/ntb_rawdev/meson.build
new file mode 100644
index 000000000..ca905049d
--- /dev/null
+++ b/drivers/raw/ntb_rawdev/meson.build
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation.
+
+deps += ['rawdev', 'mbuf', 'mempool',
+ 'pci', 'bus_pci']
+sources = files('ntb_rawdev.c')
+allow_experimental_apis = true
diff --git a/drivers/raw/ntb_rawdev/ntb_rawdev.c b/drivers/raw/ntb_rawdev/ntb_rawdev.c
new file mode 100644
index 000000000..07ad81d44
--- /dev/null
+++ b/drivers/raw/ntb_rawdev/ntb_rawdev.c
@@ -0,0 +1,488 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rte_common.h>
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_log.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_memzone.h>
+#include <rte_memcpy.h>
+#include <rte_rawdev.h>
+#include <rte_rawdev_pmd.h>
+
+#include "ntb_rawdev.h"
+
+int ntb_logtype;
+
+static const struct rte_pci_id pci_id_ntb_map[] = {
+ { .vendor_id = 0, /* sentinel */ },
+};
+
+static void
+ntb_queue_conf_get(struct rte_rawdev *dev __rte_unused,
+ uint16_t queue_id __rte_unused,
+ rte_rawdev_obj_t queue_conf __rte_unused)
+{
+}
+
+static int
+ntb_queue_setup(struct rte_rawdev *dev __rte_unused,
+ uint16_t queue_id __rte_unused,
+ rte_rawdev_obj_t queue_conf __rte_unused)
+{
+ return 0;
+}
+
+static int
+ntb_queue_release(struct rte_rawdev *dev __rte_unused,
+ uint16_t queue_id __rte_unused)
+{
+ return 0;
+}
+
+static uint16_t
+ntb_queue_count(struct rte_rawdev *dev)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ return hw->queue_pairs;
+}
+
+static int
+ntb_enqueue_bufs(struct rte_rawdev *dev,
+ struct rte_rawdev_buf **buffers,
+ unsigned int count,
+ rte_rawdev_obj_t context)
+{
+ RTE_SET_USED(dev);
+ RTE_SET_USED(buffers);
+ RTE_SET_USED(count);
+ RTE_SET_USED(context);
+
+ return 0;
+}
+
+static int
+ntb_dequeue_bufs(struct rte_rawdev *dev,
+ struct rte_rawdev_buf **buffers,
+ unsigned int count,
+ rte_rawdev_obj_t context)
+{
+ RTE_SET_USED(dev);
+ RTE_SET_USED(buffers);
+ RTE_SET_USED(count);
+ RTE_SET_USED(context);
+
+ return 0;
+}
+
+static void
+ntb_dev_info_get(struct rte_rawdev *dev, rte_rawdev_obj_t dev_info)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ struct ntb_attr *ntb_attrs = dev_info;
+
+ strncpy(ntb_attrs[NTB_TOPO_ID].name, NTB_TOPO_NAME, NTB_ATTR_NAME_LEN);
+ switch (hw->topo) {
+ case NTB_TOPO_B2B_DSD:
+ strncpy(ntb_attrs[NTB_TOPO_ID].value, "B2B DSD",
+ NTB_ATTR_VAL_LEN);
+ break;
+ case NTB_TOPO_B2B_USD:
+ strncpy(ntb_attrs[NTB_TOPO_ID].value, "B2B USD",
+ NTB_ATTR_VAL_LEN);
+ break;
+ default:
+ strncpy(ntb_attrs[NTB_TOPO_ID].value, "Unsupported",
+ NTB_ATTR_VAL_LEN);
+ }
+
+ strncpy(ntb_attrs[NTB_LINK_STATUS_ID].name, NTB_LINK_STATUS_NAME,
+ NTB_ATTR_NAME_LEN);
+ snprintf(ntb_attrs[NTB_LINK_STATUS_ID].value, NTB_ATTR_VAL_LEN,
+ "%d", hw->link_status);
+
+ strncpy(ntb_attrs[NTB_SPEED_ID].name, NTB_SPEED_NAME,
+ NTB_ATTR_NAME_LEN);
+ snprintf(ntb_attrs[NTB_SPEED_ID].value, NTB_ATTR_VAL_LEN,
+ "%d", hw->link_speed);
+
+ strncpy(ntb_attrs[NTB_WIDTH_ID].name, NTB_WIDTH_NAME,
+ NTB_ATTR_NAME_LEN);
+ snprintf(ntb_attrs[NTB_WIDTH_ID].value, NTB_ATTR_VAL_LEN,
+ "%d", hw->link_width);
+
+ strncpy(ntb_attrs[NTB_MW_CNT_ID].name, NTB_MW_CNT_NAME,
+ NTB_ATTR_NAME_LEN);
+ snprintf(ntb_attrs[NTB_MW_CNT_ID].value, NTB_ATTR_VAL_LEN,
+ "%d", hw->mw_cnt);
+
+ strncpy(ntb_attrs[NTB_DB_CNT_ID].name, NTB_DB_CNT_NAME,
+ NTB_ATTR_NAME_LEN);
+ snprintf(ntb_attrs[NTB_DB_CNT_ID].value, NTB_ATTR_VAL_LEN,
+ "%d", hw->db_cnt);
+
+ strncpy(ntb_attrs[NTB_SPAD_CNT_ID].name, NTB_SPAD_CNT_NAME,
+ NTB_ATTR_NAME_LEN);
+ snprintf(ntb_attrs[NTB_SPAD_CNT_ID].value, NTB_ATTR_VAL_LEN,
+ "%d", hw->spad_cnt);
+}
+
+static int
+ntb_dev_configure(const struct rte_rawdev *dev __rte_unused,
+ rte_rawdev_obj_t config __rte_unused)
+{
+ return 0;
+}
+
+static int
+ntb_dev_start(struct rte_rawdev *dev)
+{
+ /* TODO: init queues and start queues. */
+ dev->started = 1;
+
+ return 0;
+}
+
+static void
+ntb_dev_stop(struct rte_rawdev *dev)
+{
+ /* TODO: stop rx/tx queues. */
+ dev->started = 0;
+}
+
+static int
+ntb_dev_close(struct rte_rawdev *dev)
+{
+ int ret = 0;
+
+ if (dev->started)
+ ntb_dev_stop(dev);
+
+ /* TODO: free queues. */
+
+ return ret;
+}
+
+static int
+ntb_dev_reset(struct rte_rawdev *rawdev __rte_unused)
+{
+ return 0;
+}
+
+static int
+ntb_attr_set(struct rte_rawdev *dev, const char *attr_name,
+ uint64_t attr_value)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ int index = 0;
+
+ if (dev == NULL || attr_name == NULL) {
+ NTB_LOG(ERR, "Invalid arguments for setting attributes");
+ return -EINVAL;
+ }
+
+ if (!strncmp(attr_name, NTB_SPAD_USER, NTB_SPAD_USER_LEN)) {
+ if (hw->ntb_ops->spad_write == NULL)
+ return -ENOTSUP;
+ index = atoi(&attr_name[NTB_SPAD_USER_LEN]);
+ (*hw->ntb_ops->spad_write)(dev, hw->spad_user_list[index],
+ 1, attr_value);
+ NTB_LOG(INFO, "Set attribute (%s) Value (%" PRIu64 ")",
+ attr_name, attr_value);
+ return 0;
+ }
+
+ /* Attribute not found. */
+ NTB_LOG(ERR, "Attribute not found.");
+ return -EINVAL;
+}
+
+static int
+ntb_attr_get(struct rte_rawdev *dev, const char *attr_name,
+ uint64_t *attr_value)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ int index = 0;
+
+ if (dev == NULL || attr_name == NULL || attr_value == NULL) {
+ NTB_LOG(ERR, "Invalid arguments for getting attributes");
+ return -EINVAL;
+ }
+
+ if (!strncmp(attr_name, NTB_TOPO_NAME, NTB_ATTR_NAME_LEN)) {
+ *attr_value = hw->topo;
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ if (!strncmp(attr_name, NTB_LINK_STATUS_NAME, NTB_ATTR_NAME_LEN)) {
+ *attr_value = hw->link_status;
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ if (!strncmp(attr_name, NTB_SPEED_NAME, NTB_ATTR_NAME_LEN)) {
+ *attr_value = hw->link_speed;
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ if (!strncmp(attr_name, NTB_WIDTH_NAME, NTB_ATTR_NAME_LEN)) {
+ *attr_value = hw->link_width;
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ if (!strncmp(attr_name, NTB_MW_CNT_NAME, NTB_ATTR_NAME_LEN)) {
+ *attr_value = hw->mw_cnt;
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ if (!strncmp(attr_name, NTB_DB_CNT_NAME, NTB_ATTR_NAME_LEN)) {
+ *attr_value = hw->db_cnt;
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ if (!strncmp(attr_name, NTB_SPAD_CNT_NAME, NTB_ATTR_NAME_LEN)) {
+ *attr_value = hw->spad_cnt;
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ if (!strncmp(attr_name, NTB_SPAD_USER, NTB_SPAD_USER_LEN)) {
+ if (hw->ntb_ops->spad_read == NULL)
+ return -ENOTSUP;
+ index = atoi(&attr_name[NTB_SPAD_USER_LEN]);
+ *attr_value = (*hw->ntb_ops->spad_read)(dev,
+ hw->spad_user_list[index], 0);
+ NTB_LOG(INFO, "Attribute (%s) Value (%" PRIu64 ")",
+ attr_name, *attr_value);
+ return 0;
+ }
+
+ /* Attribute not found. */
+ NTB_LOG(ERR, "Attribute not found.");
+ return -EINVAL;
+}
+
+static int
+ntb_xstats_get(const struct rte_rawdev *dev __rte_unused,
+ const unsigned int ids[] __rte_unused,
+ uint64_t values[] __rte_unused,
+ unsigned int n __rte_unused)
+{
+ return 0;
+}
+
+static int
+ntb_xstats_get_names(const struct rte_rawdev *dev __rte_unused,
+ struct rte_rawdev_xstats_name *xstats_names __rte_unused,
+ unsigned int size __rte_unused)
+{
+ return 0;
+}
+
+static uint64_t
+ntb_xstats_get_by_name(const struct rte_rawdev *dev __rte_unused,
+ const char *name __rte_unused,
+ unsigned int *id __rte_unused)
+{
+ return 0;
+}
+
+static int
+ntb_xstats_reset(struct rte_rawdev *dev __rte_unused,
+ const uint32_t ids[] __rte_unused,
+ uint32_t nb_ids __rte_unused)
+{
+ return 0;
+}
+
+static const struct rte_rawdev_ops ntb_rawdev_ops = {
+ .dev_info_get = ntb_dev_info_get,
+ .dev_configure = ntb_dev_configure,
+ .dev_start = ntb_dev_start,
+ .dev_stop = ntb_dev_stop,
+ .dev_close = ntb_dev_close,
+ .dev_reset = ntb_dev_reset,
+
+ .queue_def_conf = ntb_queue_conf_get,
+ .queue_setup = ntb_queue_setup,
+ .queue_release = ntb_queue_release,
+ .queue_count = ntb_queue_count,
+
+ .enqueue_bufs = ntb_enqueue_bufs,
+ .dequeue_bufs = ntb_dequeue_bufs,
+
+ .attr_get = ntb_attr_get,
+ .attr_set = ntb_attr_set,
+
+ .xstats_get = ntb_xstats_get,
+ .xstats_get_names = ntb_xstats_get_names,
+ .xstats_get_by_name = ntb_xstats_get_by_name,
+ .xstats_reset = ntb_xstats_reset,
+};
+
+static int
+ntb_init_hw(struct rte_rawdev *dev, struct rte_pci_device *pci_dev)
+{
+ struct ntb_hw *hw = dev->dev_private;
+ int ret;
+
+ hw->pci_dev = pci_dev;
+ hw->peer_dev_up = 0;
+ hw->link_status = NTB_LINK_DOWN;
+ hw->link_speed = NTB_SPEED_NONE;
+ hw->link_width = NTB_WIDTH_NONE;
+
+ switch (pci_dev->id.device_id) {
+ default:
+ NTB_LOG(ERR, "Not supported device.");
+ return -EINVAL;
+ }
+
+ if (hw->ntb_ops->ntb_dev_init == NULL)
+ return -ENOTSUP;
+ ret = (*hw->ntb_ops->ntb_dev_init)(dev);
+ if (ret) {
+ NTB_LOG(ERR, "Unable to init ntb dev.");
+ return ret;
+ }
+
+ if (hw->ntb_ops->set_link == NULL)
+ return -ENOTSUP;
+ ret = (*hw->ntb_ops->set_link)(dev, 1);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int
+ntb_rawdev_create(struct rte_pci_device *pci_dev, int socket_id)
+{
+ char name[RTE_RAWDEV_NAME_MAX_LEN];
+ struct rte_rawdev *rawdev = NULL;
+ int ret;
+
+ if (pci_dev == NULL) {
+ NTB_LOG(ERR, "Invalid pci_dev.");
+ ret = -EINVAL;
+ }
+
+ memset(name, 0, sizeof(name));
+ snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "NTB:%x:%02x.%x",
+ pci_dev->addr.bus, pci_dev->addr.devid,
+ pci_dev->addr.function);
+
+ NTB_LOG(INFO, "Init %s on NUMA node %d", name, socket_id);
+
+ /* Allocate device structure. */
+ rawdev = rte_rawdev_pmd_allocate(name, sizeof(struct ntb_hw),
+ socket_id);
+ if (rawdev == NULL) {
+ NTB_LOG(ERR, "Unable to allocate rawdev.");
+ ret = -EINVAL;
+ }
+
+ rawdev->dev_ops = &ntb_rawdev_ops;
+ rawdev->device = &pci_dev->device;
+ rawdev->driver_name = pci_dev->driver->driver.name;
+
+ ret = ntb_init_hw(rawdev, pci_dev);
+ if (ret < 0) {
+ NTB_LOG(ERR, "Unable to init ntb hw.");
+ goto fail;
+ }
+
+ return ret;
+
+fail:
+ if (rawdev)
+ rte_rawdev_pmd_release(rawdev);
+
+ return ret;
+}
+
+static int
+ntb_rawdev_destroy(struct rte_pci_device *pci_dev)
+{
+ char name[RTE_RAWDEV_NAME_MAX_LEN];
+ struct rte_rawdev *rawdev;
+ int ret;
+
+ if (pci_dev == NULL) {
+ NTB_LOG(ERR, "Invalid pci_dev.");
+ ret = -EINVAL;
+ return ret;
+ }
+
+ memset(name, 0, sizeof(name));
+ snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "NTB:%x:%02x.%x",
+ pci_dev->addr.bus, pci_dev->addr.devid,
+ pci_dev->addr.function);
+
+ NTB_LOG(INFO, "Closing %s on NUMA node %d", name, rte_socket_id());
+
+ rawdev = rte_rawdev_pmd_get_named_dev(name);
+ if (rawdev == NULL) {
+ NTB_LOG(ERR, "Invalid device name (%s)", name);
+ ret = -EINVAL;
+ return ret;
+ }
+
+ ret = rte_rawdev_pmd_release(rawdev);
+ if (ret)
+ NTB_LOG(ERR, "Failed to destroy ntb rawdev.");
+
+ return ret;
+}
+
+static int
+ntb_rawdev_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ return ntb_rawdev_create(pci_dev, rte_socket_id());
+}
+
+static int
+ntb_rawdev_remove(struct rte_pci_device *pci_dev)
+{
+ return ntb_rawdev_destroy(pci_dev);
+}
+
+
+static struct rte_pci_driver rte_ntb_pmd = {
+ .id_table = pci_id_ntb_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = ntb_rawdev_probe,
+ .remove = ntb_rawdev_remove,
+};
+
+RTE_PMD_REGISTER_PCI(raw_ntb, rte_ntb_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(raw_ntb, pci_id_ntb_map);
+RTE_PMD_REGISTER_KMOD_DEP(raw_ntb, "* igb_uio | uio_pci_generic | vfio-pci");
+
+RTE_INIT(ntb_init_log)
+{
+ ntb_logtype = rte_log_register("pmd.raw.ntb");
+ if (ntb_logtype >= 0)
+ rte_log_set_level(ntb_logtype, RTE_LOG_DEBUG);
+}
diff --git a/drivers/raw/ntb_rawdev/ntb_rawdev.h b/drivers/raw/ntb_rawdev/ntb_rawdev.h
new file mode 100644
index 000000000..d355231b0
--- /dev/null
+++ b/drivers/raw/ntb_rawdev/ntb_rawdev.h
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation.
+ */
+
+#ifndef _NTB_RAWDEV_H_
+#define _NTB_RAWDEV_H_
+
+#include <stdbool.h>
+
+extern int ntb_logtype;
+
+#define NTB_LOG(level, fmt, args...) \
+ rte_log(RTE_LOG_ ## level, ntb_logtype, "%s(): " fmt "\n", \
+ __func__, ##args)
+
+/* Vendor ID */
+#define NTB_INTEL_VENDOR_ID 0x8086
+
+/* Device IDs */
+#define NTB_INTEL_DEV_ID_B2B_SKX 0x201C
+
+#define NTB_TOPO_NAME "topo"
+#define NTB_LINK_STATUS_NAME "link_status"
+#define NTB_SPEED_NAME "speed"
+#define NTB_WIDTH_NAME "width"
+#define NTB_MW_CNT_NAME "mw_count"
+#define NTB_DB_CNT_NAME "db_count"
+#define NTB_SPAD_CNT_NAME "spad_count"
+/* Reserved to app to use. */
+#define NTB_SPAD_USER "spad_user_"
+#define NTB_SPAD_USER_LEN (sizeof(NTB_SPAD_USER) - 1)
+#define NTB_SPAD_USER_MAX_NUM 10
+#define NTB_ATTR_NAME_LEN 30
+#define NTB_ATTR_VAL_LEN 30
+#define NTB_ATTR_MAX 20
+
+/* NTB Attributes */
+struct ntb_attr {
+ /**< Name of the attribute */
+ char name[NTB_ATTR_NAME_LEN];
+ /**< Value or reference of value of attribute */
+ char value[NTB_ATTR_NAME_LEN];
+};
+
+enum ntb_attr_idx {
+ NTB_TOPO_ID = 0,
+ NTB_LINK_STATUS_ID,
+ NTB_SPEED_ID,
+ NTB_WIDTH_ID,
+ NTB_MW_CNT_ID,
+ NTB_DB_CNT_ID,
+ NTB_SPAD_CNT_ID,
+};
+
+enum ntb_topo {
+ NTB_TOPO_NONE = 0,
+ NTB_TOPO_B2B_USD,
+ NTB_TOPO_B2B_DSD,
+};
+
+enum ntb_link {
+ NTB_LINK_DOWN = 0,
+ NTB_LINK_UP,
+};
+
+enum ntb_speed {
+ NTB_SPEED_NONE = 0,
+ NTB_SPEED_GEN1 = 1,
+ NTB_SPEED_GEN2 = 2,
+ NTB_SPEED_GEN3 = 3,
+ NTB_SPEED_GEN4 = 4,
+};
+
+enum ntb_width {
+ NTB_WIDTH_NONE = 0,
+ NTB_WIDTH_1 = 1,
+ NTB_WIDTH_2 = 2,
+ NTB_WIDTH_4 = 4,
+ NTB_WIDTH_8 = 8,
+ NTB_WIDTH_12 = 12,
+ NTB_WIDTH_16 = 16,
+ NTB_WIDTH_32 = 32,
+};
+
+/* Define spad registers usage. 0 is reserved. */
+enum ntb_spad_idx {
+ SPAD_NUM_MWS = 1,
+ SPAD_NUM_QPS,
+ SPAD_Q_SZ,
+ SPAD_MW0_SZ_H,
+ SPAD_MW0_SZ_L,
+ SPAD_MW1_SZ_H,
+ SPAD_MW1_SZ_L,
+};
+
+/**
+ * NTB device operations
+ * @ntb_dev_init: Init ntb dev.
+ * @get_peer_mw_addr: To get the addr of peer mw[mw_idx].
+ * @mw_set_trans: Set translation of internal memory that remote can access.
+ * @get_link_status: get link status, link speed and link width.
+ * @set_link: Set local side up/down.
+ * @spad_read: Read local/peer spad register val.
+ * @spad_write: Write val to local/peer spad register.
+ * @db_read: Read doorbells status.
+ * @db_clear: Clear local doorbells.
+ * @db_set_mask: Set bits in db mask, preventing db interrpts generated
+ * for those db bits.
+ * @peer_db_set: Set doorbell bit to generate peer interrupt for that bit.
+ * @vector_bind: Bind vector source [intr] to msix vector [msix].
+ */
+struct ntb_dev_ops {
+ int (*ntb_dev_init)(struct rte_rawdev *dev);
+ void *(*get_peer_mw_addr)(struct rte_rawdev *dev, int mw_idx);
+ int (*mw_set_trans)(struct rte_rawdev *dev, int mw_idx,
+ uint64_t addr, uint64_t size);
+ int (*get_link_status)(struct rte_rawdev *dev);
+ int (*set_link)(struct rte_rawdev *dev, bool up);
+ uint32_t (*spad_read)(struct rte_rawdev *dev, int spad, bool peer);
+ int (*spad_write)(struct rte_rawdev *dev, int spad,
+ bool peer, uint32_t spad_v);
+ uint64_t (*db_read)(struct rte_rawdev *dev);
+ int (*db_clear)(struct rte_rawdev *dev, uint64_t db_bits);
+ int (*db_set_mask)(struct rte_rawdev *dev, uint64_t db_mask);
+ int (*peer_db_set)(struct rte_rawdev *dev, uint8_t db_bit);
+ int (*vector_bind)(struct rte_rawdev *dev, uint8_t intr, uint8_t msix);
+};
+
+/* ntb private data. */
+struct ntb_hw {
+ uint8_t mw_cnt;
+ uint8_t peer_mw_cnt;
+ uint8_t db_cnt;
+ uint8_t spad_cnt;
+
+ uint64_t db_valid_mask;
+ uint64_t db_mask;
+
+ enum ntb_topo topo;
+
+ enum ntb_link link_status;
+ enum ntb_speed link_speed;
+ enum ntb_width link_width;
+
+ const struct ntb_dev_ops *ntb_ops;
+
+ struct rte_pci_device *pci_dev;
+ char *hw_addr;
+
+ uint64_t *mw_size;
+ uint64_t *peer_mw_size;
+ uint8_t peer_dev_up;
+
+ uint16_t queue_pairs;
+ uint16_t queue_size;
+
+ /**< mem zone to populate RX ring. */
+ const struct rte_memzone **mz;
+
+ /* Reserve several spad for app to use. */
+ int spad_user_list[NTB_SPAD_USER_MAX_NUM];
+};
+
+#endif /* _NTB_RAWDEV_H_ */
diff --git a/drivers/raw/ntb_rawdev/rte_pmd_ntb_rawdev_version.map b/drivers/raw/ntb_rawdev/rte_pmd_ntb_rawdev_version.map
new file mode 100644
index 000000000..8861484fb
--- /dev/null
+++ b/drivers/raw/ntb_rawdev/rte_pmd_ntb_rawdev_version.map
@@ -0,0 +1,4 @@
+DPDK_19.08 {
+
+ local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index d0df0b023..ff17bef46 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -301,6 +301,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_IFPGA_BUS),y)
_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_IFPGA_RAWDEV) += -lrte_pmd_ifpga_rawdev
_LDLIBS-$(CONFIG_RTE_LIBRTE_IPN3KE_PMD) += -lrte_pmd_ipn3ke
endif # CONFIG_RTE_LIBRTE_IFPGA_BUS
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += -lrte_pmd_ntb_rawdev
endif # CONFIG_RTE_LIBRTE_RAWDEV
endif # !CONFIG_RTE_BUILD_SHARED_LIBS
--
2.17.1
^ permalink raw reply related
* [dpdk-dev] [PATCH v7 0/6] rawdev driver for ntb
From: Xiaoyun Li @ 2019-06-20 10:21 UTC (permalink / raw)
To: jingjing.wu, keith.wiles, cunming.liang, omkar.maslekar; +Cc: dev, Xiaoyun Li
In-Reply-To: <20190618021055.12709-1-xiaoyun.li@intel.com>
This patch set adds support for Intel NTB device with Skylake platform.
It is a raw device for allowing two hosts to communicate with each other
and access the peer memory.
This patch set also provides a simple example to transmit a file between
two hosts. But since there is no FIFO here, only support file which is
no more than 4M. And will add FIFO in the future.
v7:
* Fixed a typo.
* Generic spad registers to be spad_user and the specific spad is
* defined by the specific hw.
* Refined the codes by replacing with lib functions such as rte_read32.
* Rebased the codes to the newest dpdk-next-net-intel branch.
v6:
* Fixed a typo.
v5:
* Actual v4. v4 patchset is the same as v3.
v4:
* Fix compile issues of comparison of array with null pointer.
v3:
* Fixed compilation issues with target i686.
* Renamed communication devices to misc devices in usertool.
* Rebased to the newest dpdk-next-net-intel branch.
v2:
* Replaced ! with NULL check for pointers.
* Added ntb_ops valid check before use it.
* Replaced RTE_MEMZONE_1GB with RTE_MEMZONE_IOVA_CONTIG in case users do
not use 1G hugepage.
* Added a timeout for dev_stop handshake in case that the peer stopped
abnormally such as crashed while debugging.
* Updated docs especailly about how to setup BIOS for skylake.
* Fixed not return issue and not free issue in example.
* Renamed ntb_devices to communication_devices to be more generic in
usertools.
* Polish the codes and docs.
Xiaoyun Li (6):
raw/ntb: introduce ntb rawdev driver
raw/ntb: add intel ntb support
raw/ntb: add handshake process
examples/ntb: enable an example for ntb
usertools/dpdk-devbind.py: add support for ntb
doc: update docs for ntb driver
MAINTAINERS | 8 +
config/common_base | 5 +
doc/guides/rawdevs/index.rst | 1 +
doc/guides/rawdevs/ntb_rawdev.rst | 41 +
doc/guides/rel_notes/release_19_08.rst | 15 +
doc/guides/sample_app_ug/index.rst | 1 +
doc/guides/sample_app_ug/ntb.rst | 47 +
drivers/raw/Makefile | 1 +
drivers/raw/meson.build | 2 +-
drivers/raw/ntb_rawdev/Makefile | 28 +
drivers/raw/ntb_rawdev/meson.build | 8 +
drivers/raw/ntb_rawdev/ntb_hw_intel.c | 369 ++++++++
drivers/raw/ntb_rawdev/ntb_hw_intel.h | 86 ++
drivers/raw/ntb_rawdev/ntb_rawdev.c | 839 ++++++++++++++++++
drivers/raw/ntb_rawdev/ntb_rawdev.h | 164 ++++
.../ntb_rawdev/rte_pmd_ntb_rawdev_version.map | 4 +
examples/Makefile | 1 +
examples/meson.build | 2 +-
examples/ntb/Makefile | 68 ++
examples/ntb/meson.build | 16 +
examples/ntb/ntb_fwd.c | 377 ++++++++
mk/rte.app.mk | 1 +
usertools/dpdk-devbind.py | 9 +
23 files changed, 2091 insertions(+), 2 deletions(-)
create mode 100644 doc/guides/rawdevs/ntb_rawdev.rst
create mode 100644 doc/guides/sample_app_ug/ntb.rst
create mode 100644 drivers/raw/ntb_rawdev/Makefile
create mode 100644 drivers/raw/ntb_rawdev/meson.build
create mode 100644 drivers/raw/ntb_rawdev/ntb_hw_intel.c
create mode 100644 drivers/raw/ntb_rawdev/ntb_hw_intel.h
create mode 100644 drivers/raw/ntb_rawdev/ntb_rawdev.c
create mode 100644 drivers/raw/ntb_rawdev/ntb_rawdev.h
create mode 100644 drivers/raw/ntb_rawdev/rte_pmd_ntb_rawdev_version.map
create mode 100644 examples/ntb/Makefile
create mode 100644 examples/ntb/meson.build
create mode 100644 examples/ntb/ntb_fwd.c
--
2.17.1
^ permalink raw reply
* Re: [dpdk-dev] [PATCH v2 02/10] meson: add BUILDING_RTE_SDK
From: Bruce Richardson @ 2019-06-20 10:21 UTC (permalink / raw)
To: Neil Horman; +Cc: dev, Jerin Jacob Kollanukkaran, Thomas Monjalon
In-Reply-To: <20190613142344.9188-3-nhorman@tuxdriver.com>
On Thu, Jun 13, 2019 at 10:23:36AM -0400, Neil Horman wrote:
> The __rte_internal macro is defined dependent on the value of the build
> environment variable BUILDING_RTE_SDK. This variable was set in the
> Makefile environment but not the meson environment, so lets reconcile
> the two by defining it for meson in the lib and drivers directories, but
> not the examples/apps directories, which should be treated as they are
> not part of the core DPDK library
>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> CC: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
> CC: Bruce Richardson <bruce.richardson@intel.com>
> CC: Thomas Monjalon <thomas@monjalon.net>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.