* [RESEND PATCH v3 3/3] sh: add the sh_ prefix to early platform symbols
From: Bartosz Golaszewski @ 2018-06-21 8:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180621082321.4259-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Old early platform device support is now sh-specific. Before moving on
to implementing new early platform framework based on real platform
devices, prefix all early platform symbols with 'sh_'.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
arch/sh/drivers/platform_early.c | 66 +++++++++++++-------------
arch/sh/include/asm/platform_early.h | 30 ++++++------
arch/sh/kernel/cpu/sh2/setup-sh7619.c | 2 +-
arch/sh/kernel/cpu/sh2a/setup-mxg.c | 2 +-
arch/sh/kernel/cpu/sh2a/setup-sh7201.c | 2 +-
arch/sh/kernel/cpu/sh2a/setup-sh7203.c | 2 +-
arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 2 +-
arch/sh/kernel/cpu/sh2a/setup-sh7264.c | 2 +-
arch/sh/kernel/cpu/sh2a/setup-sh7269.c | 2 +-
arch/sh/kernel/cpu/sh3/setup-sh7705.c | 2 +-
arch/sh/kernel/cpu/sh3/setup-sh770x.c | 2 +-
arch/sh/kernel/cpu/sh3/setup-sh7710.c | 2 +-
arch/sh/kernel/cpu/sh3/setup-sh7720.c | 2 +-
arch/sh/kernel/cpu/sh4/setup-sh4-202.c | 2 +-
arch/sh/kernel/cpu/sh4/setup-sh7750.c | 8 ++--
arch/sh/kernel/cpu/sh4/setup-sh7760.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7734.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7763.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7770.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7780.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7785.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7786.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-shx3.c | 2 +-
arch/sh/kernel/cpu/sh5/setup-sh5.c | 2 +-
arch/sh/kernel/setup.c | 2 +-
arch/sh/kernel/time.c | 4 +-
drivers/clocksource/sh_cmt.c | 6 +--
drivers/clocksource/sh_mtu2.c | 6 +--
drivers/clocksource/sh_tmu.c | 6 +--
drivers/tty/serial/sh-sci.c | 4 +-
include/linux/platform_device.h | 2 +-
37 files changed, 94 insertions(+), 94 deletions(-)
diff --git a/arch/sh/drivers/platform_early.c b/arch/sh/drivers/platform_early.c
index bc094f6eb366..6eba755b8c12 100644
--- a/arch/sh/drivers/platform_early.c
+++ b/arch/sh/drivers/platform_early.c
@@ -3,8 +3,8 @@
#include <asm/platform_early.h>
#include <linux/pm.h>
-static __initdata LIST_HEAD(early_platform_driver_list);
-static __initdata LIST_HEAD(early_platform_device_list);
+static __initdata LIST_HEAD(sh_early_platform_driver_list);
+static __initdata LIST_HEAD(sh_early_platform_device_list);
static const struct platform_device_id *
platform_match_id(const struct platform_device_id *id,
@@ -57,13 +57,13 @@ static void pm_runtime_early_init(struct device *dev) {}
#endif
/**
- * early_platform_driver_register - register early platform driver
- * @epdrv: early_platform driver structure
+ * sh_early_platform_driver_register - register early platform driver
+ * @epdrv: sh_early_platform driver structure
* @buf: string passed from early_param()
*
- * Helper function for early_platform_init() / early_platform_init_buffer()
+ * Helper function for sh_early_platform_init() / sh_early_platform_init_buffer()
*/
-int __init early_platform_driver_register(struct early_platform_driver *epdrv,
+int __init sh_early_platform_driver_register(struct sh_early_platform_driver *epdrv,
char *buf)
{
char *tmp;
@@ -74,7 +74,7 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv,
*/
if (!epdrv->list.next) {
INIT_LIST_HEAD(&epdrv->list);
- list_add_tail(&epdrv->list, &early_platform_driver_list);
+ list_add_tail(&epdrv->list, &sh_early_platform_driver_list);
}
/* If the user has specified device then make sure the driver
@@ -83,7 +83,7 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv,
*/
n = strlen(epdrv->pdrv->driver.name);
if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
- list_move(&epdrv->list, &early_platform_driver_list);
+ list_move(&epdrv->list, &sh_early_platform_driver_list);
/* Allow passing parameters after device name */
if (buf[n] == '\0' || buf[n] == ',')
@@ -113,14 +113,14 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv,
}
/**
- * early_platform_add_devices - adds a number of early platform devices
+ * sh_early_platform_add_devices - adds a number of early platform devices
* @devs: array of early platform devices to add
* @num: number of early platform devices in array
*
* Used by early architecture code to register early platform devices and
* their platform data.
*/
-void __init early_platform_add_devices(struct platform_device **devs, int num)
+void __init sh_early_platform_add_devices(struct platform_device **devs, int num)
{
struct device *dev;
int i;
@@ -133,20 +133,20 @@ void __init early_platform_add_devices(struct platform_device **devs, int num)
pm_runtime_early_init(dev);
INIT_LIST_HEAD(&dev->devres_head);
list_add_tail(&dev->devres_head,
- &early_platform_device_list);
+ &sh_early_platform_device_list);
}
}
}
/**
- * early_platform_driver_register_all - register early platform drivers
+ * sh_early_platform_driver_register_all - register early platform drivers
* @class_str: string to identify early platform driver class
*
* Used by architecture code to register all early platform drivers
* for a certain class. If omitted then only early platform drivers
* with matching kernel command line class parameters will be registered.
*/
-void __init early_platform_driver_register_all(char *class_str)
+void __init sh_early_platform_driver_register_all(char *class_str)
{
/* The "class_str" parameter may or may not be present on the kernel
* command line. If it is present then there may be more than one
@@ -159,23 +159,23 @@ void __init early_platform_driver_register_all(char *class_str)
* We use parse_early_options() to make sure the early_param() gets
* called at least once. The early_param() may be called more than
* once since the name of the preferred device may be specified on
- * the kernel command line. early_platform_driver_register() handles
+ * the kernel command line. sh_early_platform_driver_register() handles
* this case for us.
*/
parse_early_options(class_str);
}
/**
- * early_platform_match - find early platform device matching driver
+ * sh_early_platform_match - find early platform device matching driver
* @epdrv: early platform driver structure
* @id: id to match against
*/
static struct platform_device * __init
-early_platform_match(struct early_platform_driver *epdrv, int id)
+sh_early_platform_match(struct sh_early_platform_driver *epdrv, int id)
{
struct platform_device *pd;
- list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
+ list_for_each_entry(pd, &sh_early_platform_device_list, dev.devres_head)
if (platform_match(&pd->dev, &epdrv->pdrv->driver))
if (pd->id == id)
return pd;
@@ -184,16 +184,16 @@ early_platform_match(struct early_platform_driver *epdrv, int id)
}
/**
- * early_platform_left - check if early platform driver has matching devices
+ * sh_early_platform_left - check if early platform driver has matching devices
* @epdrv: early platform driver structure
* @id: return true if id or above exists
*/
-static int __init early_platform_left(struct early_platform_driver *epdrv,
+static int __init sh_early_platform_left(struct sh_early_platform_driver *epdrv,
int id)
{
struct platform_device *pd;
- list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
+ list_for_each_entry(pd, &sh_early_platform_device_list, dev.devres_head)
if (platform_match(&pd->dev, &epdrv->pdrv->driver))
if (pd->id >= id)
return 1;
@@ -202,22 +202,22 @@ static int __init early_platform_left(struct early_platform_driver *epdrv,
}
/**
- * early_platform_driver_probe_id - probe drivers matching class_str and id
+ * sh_early_platform_driver_probe_id - probe drivers matching class_str and id
* @class_str: string to identify early platform driver class
* @id: id to match against
* @nr_probe: number of platform devices to successfully probe before exiting
*/
-static int __init early_platform_driver_probe_id(char *class_str,
+static int __init sh_early_platform_driver_probe_id(char *class_str,
int id,
int nr_probe)
{
- struct early_platform_driver *epdrv;
+ struct sh_early_platform_driver *epdrv;
struct platform_device *match;
int match_id;
int n = 0;
int left = 0;
- list_for_each_entry(epdrv, &early_platform_driver_list, list) {
+ list_for_each_entry(epdrv, &sh_early_platform_driver_list, list) {
/* only use drivers matching our class_str */
if (strcmp(class_str, epdrv->class_str))
continue;
@@ -228,7 +228,7 @@ static int __init early_platform_driver_probe_id(char *class_str,
} else {
match_id = id;
- left += early_platform_left(epdrv, id);
+ left += sh_early_platform_left(epdrv, id);
/* skip requested id */
switch (epdrv->requested_id) {
@@ -250,7 +250,7 @@ static int __init early_platform_driver_probe_id(char *class_str,
match = NULL;
break;
default:
- match = early_platform_match(epdrv, match_id);
+ match = sh_early_platform_match(epdrv, match_id);
}
if (match) {
@@ -292,7 +292,7 @@ static int __init early_platform_driver_probe_id(char *class_str,
}
/**
- * early_platform_driver_probe - probe a class of registered drivers
+ * sh_early_platform_driver_probe - probe a class of registered drivers
* @class_str: string to identify early platform driver class
* @nr_probe: number of platform devices to successfully probe before exiting
* @user_only: only probe user specified early platform devices
@@ -301,7 +301,7 @@ static int __init early_platform_driver_probe_id(char *class_str,
* within a certain class. For probe to happen a registered early platform
* device matching a registered early platform driver is needed.
*/
-int __init early_platform_driver_probe(char *class_str,
+int __init sh_early_platform_driver_probe(char *class_str,
int nr_probe,
int user_only)
{
@@ -309,7 +309,7 @@ int __init early_platform_driver_probe(char *class_str,
n = 0;
for (i = -2; n < nr_probe; i++) {
- k = early_platform_driver_probe_id(class_str, i, nr_probe - n);
+ k = sh_early_platform_driver_probe_id(class_str, i, nr_probe - n);
if (k < 0)
break;
@@ -324,14 +324,14 @@ int __init early_platform_driver_probe(char *class_str,
}
/**
- * early_platform_cleanup - clean up early platform code
+ * sh_early_platform_cleanup - clean up early platform code
*/
-static int __init early_platform_cleanup(void)
+static int __init sh_early_platform_cleanup(void)
{
struct platform_device *pd, *pd2;
/* clean up the devres list used to chain devices */
- list_for_each_entry_safe(pd, pd2, &early_platform_device_list,
+ list_for_each_entry_safe(pd, pd2, &sh_early_platform_device_list,
dev.devres_head) {
list_del(&pd->dev.devres_head);
memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
@@ -343,4 +343,4 @@ static int __init early_platform_cleanup(void)
* This must happen once after all early devices are probed but before probing
* real platform devices.
*/
-subsys_initcall(early_platform_cleanup);
+subsys_initcall(sh_early_platform_cleanup);
diff --git a/arch/sh/include/asm/platform_early.h b/arch/sh/include/asm/platform_early.h
index 4590ab757d5f..fc802137c37d 100644
--- a/arch/sh/include/asm/platform_early.h
+++ b/arch/sh/include/asm/platform_early.h
@@ -8,7 +8,7 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
-struct early_platform_driver {
+struct sh_early_platform_driver {
const char *class_str;
struct platform_driver *pdrv;
struct list_head list;
@@ -20,39 +20,39 @@ struct early_platform_driver {
#define EARLY_PLATFORM_ID_UNSET -2
#define EARLY_PLATFORM_ID_ERROR -3
-extern int early_platform_driver_register(struct early_platform_driver *epdrv,
+extern int sh_early_platform_driver_register(struct sh_early_platform_driver *epdrv,
char *buf);
-extern void early_platform_add_devices(struct platform_device **devs, int num);
+extern void sh_early_platform_add_devices(struct platform_device **devs, int num);
-static inline int is_early_platform_device(struct platform_device *pdev)
+static inline int is_sh_early_platform_device(struct platform_device *pdev)
{
return !pdev->dev.driver;
}
-extern void early_platform_driver_register_all(char *class_str);
-extern int early_platform_driver_probe(char *class_str,
+extern void sh_early_platform_driver_register_all(char *class_str);
+extern int sh_early_platform_driver_probe(char *class_str,
int nr_probe, int user_only);
-#define early_platform_init(class_string, platdrv) \
- early_platform_init_buffer(class_string, platdrv, NULL, 0)
+#define sh_early_platform_init(class_string, platdrv) \
+ sh_early_platform_init_buffer(class_string, platdrv, NULL, 0)
#ifndef MODULE
-#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz) \
-static __initdata struct early_platform_driver early_driver = { \
+#define sh_early_platform_init_buffer(class_string, platdrv, buf, bufsiz) \
+static __initdata struct sh_early_platform_driver early_driver = { \
.class_str = class_string, \
.buffer = buf, \
.bufsize = bufsiz, \
.pdrv = platdrv, \
.requested_id = EARLY_PLATFORM_ID_UNSET, \
}; \
-static int __init early_platform_driver_setup_func(char *buffer) \
+static int __init sh_early_platform_driver_setup_func(char *buffer) \
{ \
- return early_platform_driver_register(&early_driver, buffer); \
+ return sh_early_platform_driver_register(&early_driver, buffer); \
} \
-early_param(class_string, early_platform_driver_setup_func)
+early_param(class_string, sh_early_platform_driver_setup_func)
#else /* MODULE */
-#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz) \
-static inline char *early_platform_driver_setup_func(void) \
+#define sh_early_platform_init_buffer(class_string, platdrv, buf, bufsiz) \
+static inline char *sh_early_platform_driver_setup_func(void) \
{ \
return bufsiz ? buf : NULL; \
}
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index a02fc03baef8..6d0425affa71 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -203,6 +203,6 @@ void __init plat_early_device_setup(void)
/* enable CMT clock */
__raw_writeb(__raw_readb(STBCR3) & ~0x10, STBCR3);
- early_platform_add_devices(sh7619_early_devices,
+ sh_early_platform_add_devices(sh7619_early_devices,
ARRAY_SIZE(sh7619_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
index d33568a12fad..fb9dd473a9cc 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
@@ -173,6 +173,6 @@ static struct platform_device *mxg_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(mxg_early_devices,
+ sh_early_platform_add_devices(mxg_early_devices,
ARRAY_SIZE(mxg_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
index b258c5c3af60..37357d0fc9bc 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
@@ -416,6 +416,6 @@ void __init plat_early_device_setup(void)
/* enable MTU2 clock */
__raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
- early_platform_add_devices(sh7201_early_devices,
+ sh_early_platform_add_devices(sh7201_early_devices,
ARRAY_SIZE(sh7201_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
index db3f8df8d76d..79ba8d0db6b0 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
@@ -353,6 +353,6 @@ void __init plat_early_device_setup(void)
/* enable MTU2 clock */
__raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
- early_platform_add_devices(sh7203_early_devices,
+ sh_early_platform_add_devices(sh7203_early_devices,
ARRAY_SIZE(sh7203_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index e1be4fedc739..501922504a3f 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -289,6 +289,6 @@ void __init plat_early_device_setup(void)
/* enable MTU2 clock */
__raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
- early_platform_add_devices(sh7206_early_devices,
+ sh_early_platform_add_devices(sh7206_early_devices,
ARRAY_SIZE(sh7206_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7264.c b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
index b5bed10d0d72..955f15386bbd 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
@@ -550,6 +550,6 @@ static struct platform_device *sh7264_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7264_early_devices,
+ sh_early_platform_add_devices(sh7264_early_devices,
ARRAY_SIZE(sh7264_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7269.c b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
index 248a6732397a..d8ecb24a0888 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
@@ -566,6 +566,6 @@ static struct platform_device *sh7269_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7269_early_devices,
+ sh_early_platform_add_devices(sh7269_early_devices,
ARRAY_SIZE(sh7269_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index 7ec8c11c2f7a..481cfbc3b82d 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -182,7 +182,7 @@ static struct platform_device *sh7705_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7705_early_devices,
+ sh_early_platform_add_devices(sh7705_early_devices,
ARRAY_SIZE(sh7705_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
index 20839dd40a2f..d0cd14f5fc19 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
@@ -234,7 +234,7 @@ static struct platform_device *sh770x_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh770x_early_devices,
+ sh_early_platform_add_devices(sh770x_early_devices,
ARRAY_SIZE(sh770x_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 780ccd202bab..fb680bae22c3 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -181,7 +181,7 @@ static struct platform_device *sh7710_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7710_early_devices,
+ sh_early_platform_add_devices(sh7710_early_devices,
ARRAY_SIZE(sh7710_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index 723bd9c04c8a..faf084cbbbed 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -215,7 +215,7 @@ static struct platform_device *sh7720_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7720_early_devices,
+ sh_early_platform_add_devices(sh7720_early_devices,
ARRAY_SIZE(sh7720_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
index 4a5fa86006cd..123b848368d4 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
@@ -80,7 +80,7 @@ static struct platform_device *sh4202_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh4202_early_devices,
+ sh_early_platform_add_devices(sh4202_early_devices,
ARRAY_SIZE(sh4202_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index abb3703c2273..8f6c83b745db 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -165,15 +165,15 @@ void __init plat_early_device_setup(void)
if (mach_is_rts7751r2d()) {
scif_platform_data.scscr |= SCSCR_CKE1;
dev[0] = &scif_device;
- early_platform_add_devices(dev, 1);
+ sh_early_platform_add_devices(dev, 1);
} else {
dev[0] = &sci_device;
- early_platform_add_devices(dev, 1);
+ sh_early_platform_add_devices(dev, 1);
dev[0] = &scif_device;
- early_platform_add_devices(dev, 1);
+ sh_early_platform_add_devices(dev, 1);
}
- early_platform_add_devices(sh7750_early_devices,
+ sh_early_platform_add_devices(sh7750_early_devices,
ARRAY_SIZE(sh7750_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 649f4dcb5935..ab8cc1826d8c 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -275,7 +275,7 @@ static struct platform_device *sh7760_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7760_early_devices,
+ sh_early_platform_add_devices(sh7760_early_devices,
ARRAY_SIZE(sh7760_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 73715a635048..a3ff0803b62e 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -300,7 +300,7 @@ static struct platform_device *sh7343_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7343_early_devices,
+ sh_early_platform_add_devices(sh7343_early_devices,
ARRAY_SIZE(sh7343_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 942856048112..2ad400fef830 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -244,7 +244,7 @@ static struct platform_device *sh7366_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7366_early_devices,
+ sh_early_platform_add_devices(sh7366_early_devices,
ARRAY_SIZE(sh7366_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index bf60456a8012..01e687d72c16 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -516,7 +516,7 @@ static struct platform_device *sh7722_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7722_early_devices,
+ sh_early_platform_add_devices(sh7722_early_devices,
ARRAY_SIZE(sh7722_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index d25d3c3b44ab..6738c39413b2 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -414,7 +414,7 @@ static struct platform_device *sh7723_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7723_early_devices,
+ sh_early_platform_add_devices(sh7723_early_devices,
ARRAY_SIZE(sh7723_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 0eeadabc8065..0163750a3fb0 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -834,7 +834,7 @@ static struct platform_device *sh7724_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7724_early_devices,
+ sh_early_platform_add_devices(sh7724_early_devices,
ARRAY_SIZE(sh7724_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7734.c b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c
index bed9d01fa85f..d3760029f0f3 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7734.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c
@@ -284,7 +284,7 @@ static struct platform_device *sh7734_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7734_early_devices,
+ sh_early_platform_add_devices(sh7734_early_devices,
ARRAY_SIZE(sh7734_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index b5b19e81a8dc..25d655ab4114 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -771,7 +771,7 @@ static struct platform_device *sh7757_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7757_early_devices,
+ sh_early_platform_add_devices(sh7757_early_devices,
ARRAY_SIZE(sh7757_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index 51a6c64f860e..42f234efaa42 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -225,7 +225,7 @@ static struct platform_device *sh7763_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7763_early_devices,
+ sh_early_platform_add_devices(sh7763_early_devices,
ARRAY_SIZE(sh7763_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
index 77f228e20599..35420329f5e1 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
@@ -320,7 +320,7 @@ static struct platform_device *sh7770_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7770_early_devices,
+ sh_early_platform_add_devices(sh7770_early_devices,
ARRAY_SIZE(sh7770_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index c4cbb7584122..3a75db564c24 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -289,7 +289,7 @@ void __init plat_early_device_setup(void)
scif1_platform_data.scscr &= ~SCSCR_CKE1;
}
- early_platform_add_devices(sh7780_early_devices,
+ sh_early_platform_add_devices(sh7780_early_devices,
ARRAY_SIZE(sh7780_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index eda0d61ebf71..eb3c003223e2 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -357,7 +357,7 @@ static struct platform_device *sh7785_early_devices[] __initdata = {
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7785_early_devices,
+ sh_early_platform_add_devices(sh7785_early_devices,
ARRAY_SIZE(sh7785_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index 77226a60c36f..46473345cb79 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -838,6 +838,6 @@ arch_initcall(sh7786_devices_setup);
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh7786_early_devices,
+ sh_early_platform_add_devices(sh7786_early_devices,
ARRAY_SIZE(sh7786_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
index 83feaf0a4aae..c531182425f7 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -156,7 +156,7 @@ arch_initcall(shx3_devices_setup);
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(shx3_early_devices,
+ sh_early_platform_add_devices(shx3_early_devices,
ARRAY_SIZE(shx3_early_devices));
}
diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c
index 8ebd26a9fd90..034bb36bfdc2 100644
--- a/arch/sh/kernel/cpu/sh5/setup-sh5.c
+++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c
@@ -119,6 +119,6 @@ arch_initcall(sh5_devices_setup);
void __init plat_early_device_setup(void)
{
- early_platform_add_devices(sh5_early_devices,
+ sh_early_platform_add_devices(sh5_early_devices,
ARRAY_SIZE(sh5_early_devices));
}
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index aed8f331f66b..74548fc31a3d 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -328,7 +328,7 @@ void __init setup_arch(char **cmdline_p)
sh_mv_setup();
/* Let earlyprintk output early console messages */
- early_platform_driver_probe("earlyprintk", 1, 1);
+ sh_early_platform_driver_probe("earlyprintk", 1, 1);
#ifdef CONFIG_OF_FLATTREE
#ifdef CONFIG_USE_BUILTIN_DTB
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 674d8413491b..9c460a74e3c2 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -105,8 +105,8 @@ static void __init sh_late_time_init(void)
* clocksource and the jiffies clocksource is used transparently
* instead. No error handling is necessary here.
*/
- early_platform_driver_register_all("earlytimer");
- early_platform_driver_probe("earlytimer", 2, 0);
+ sh_early_platform_driver_register_all("earlytimer");
+ sh_early_platform_driver_probe("earlytimer", 2, 0);
}
void __init time_init(void)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index fe9abe5b3e68..49f36c26e6fb 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -1047,7 +1047,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
struct sh_cmt_device *cmt = platform_get_drvdata(pdev);
int ret;
- if (!is_early_platform_device(pdev)) {
+ if (!is_sh_early_platform_device(pdev)) {
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
}
@@ -1067,7 +1067,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
pm_runtime_idle(&pdev->dev);
return ret;
}
- if (is_early_platform_device(pdev))
+ if (is_sh_early_platform_device(pdev))
return 0;
out:
@@ -1105,7 +1105,7 @@ static void __exit sh_cmt_exit(void)
}
#ifdef CONFIG_SUPERH
-early_platform_init("earlytimer", &sh_cmt_device_driver);
+sh_early_platform_init("earlytimer", &sh_cmt_device_driver);
#endif
subsys_initcall(sh_cmt_init);
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index becff3a1a6fb..05120ef24833 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -454,7 +454,7 @@ static int sh_mtu2_probe(struct platform_device *pdev)
struct sh_mtu2_device *mtu = platform_get_drvdata(pdev);
int ret;
- if (!is_early_platform_device(pdev)) {
+ if (!is_sh_early_platform_device(pdev)) {
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
}
@@ -474,7 +474,7 @@ static int sh_mtu2_probe(struct platform_device *pdev)
pm_runtime_idle(&pdev->dev);
return ret;
}
- if (is_early_platform_device(pdev))
+ if (is_sh_early_platform_device(pdev))
return 0;
out:
@@ -524,7 +524,7 @@ static void __exit sh_mtu2_exit(void)
}
#ifdef CONFIG_SUPERH
-early_platform_init("earlytimer", &sh_mtu2_device_driver);
+sh_early_platform_init("earlytimer", &sh_mtu2_device_driver);
#endif
subsys_initcall(sh_mtu2_init);
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 3f4783a9ecf0..6f2c5279c1fd 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -610,7 +610,7 @@ static int sh_tmu_probe(struct platform_device *pdev)
struct sh_tmu_device *tmu = platform_get_drvdata(pdev);
int ret;
- if (!is_early_platform_device(pdev)) {
+ if (!is_sh_early_platform_device(pdev)) {
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
}
@@ -631,7 +631,7 @@ static int sh_tmu_probe(struct platform_device *pdev)
return ret;
}
- if (is_early_platform_device(pdev))
+ if (is_sh_early_platform_device(pdev))
return 0;
out:
@@ -682,7 +682,7 @@ static void __exit sh_tmu_exit(void)
}
#ifdef CONFIG_SUPERH
-early_platform_init("earlytimer", &sh_tmu_device_driver);
+sh_early_platform_init("earlytimer", &sh_tmu_device_driver);
#endif
subsys_initcall(sh_tmu_init);
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index a6c3aa7a7de8..1d2e645f35d5 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -3220,7 +3220,7 @@ static int sci_probe(struct platform_device *dev)
* to make it beyond this yet.
*/
#ifdef CONFIG_SUPERH
- if (is_early_platform_device(dev))
+ if (is_sh_early_platform_device(dev))
return sci_probe_earlyprintk(dev);
#endif
@@ -3320,7 +3320,7 @@ static void __exit sci_exit(void)
}
#if defined(CONFIG_SUPERH) && defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
-early_platform_init_buffer("earlyprintk", &sci_driver,
+sh_early_platform_init_buffer("earlyprintk", &sci_driver,
early_serial_buf, ARRAY_SIZE(early_serial_buf));
#endif
#ifdef CONFIG_SERIAL_SH_SCI_EARLYCON
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 7d7610da8377..a03d5cd7dc5a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -324,7 +324,7 @@ extern int platform_dma_configure(struct device *dev);
* drivers. It should go away once we introduce the new platform_device-based
* early driver framework.
*/
-static inline int is_early_platform_device(struct platform_device *pdev)
+static inline int is_sh_early_platform_device(struct platform_device *pdev)
{
return 0;
}
--
2.17.1
^ permalink raw reply related
* [PATCH v2 5/8] mailbox: tegra-hsp: Add support for shared mailboxes
From: Jon Hunter @ 2018-06-21 8:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620122042.10950-6-mperttunen@nvidia.com>
On 20/06/18 13:20, Mikko Perttunen wrote:
> The Tegra HSP block supports 'shared mailboxes' that are simple 32-bit
> registers consisting of a FULL bit in MSB position and 31 bits of data.
> The hardware can be configured to trigger interrupts when a mailbox
> is empty or full. Add support for these shared mailboxes to the HSP
> driver.
>
> The initial use for the mailboxes is the Tegra Combined UART. For this
> purpose, we use interrupts to receive data, and spinning to wait for
> the transmit mailbox to be emptied to minimize unnecessary overhead.
>
> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
>
> Notes:
> v2:
> - Added defines for some register fields
> - Simplified bit looping logic in interrupt handler
> - Changed write done polling to use readl_poll_timeout
> - Removed unnecessary zero assignments
> - Fixed two error cases in probe to do proper cleanup
>
> drivers/mailbox/tegra-hsp.c | 210 +++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 190 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
> index 5dc21a6d01bb..6864446417c9 100644
> --- a/drivers/mailbox/tegra-hsp.c
> +++ b/drivers/mailbox/tegra-hsp.c
> @@ -13,6 +13,7 @@
>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> +#include <linux/iopoll.h>
> #include <linux/mailbox_controller.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> @@ -21,6 +22,13 @@
>
> #include <dt-bindings/mailbox/tegra186-hsp.h>
>
> +#include "mailbox.h"
> +
> +#define HSP_INT0_IE 0x100
> +#define HSP_INT_IR 0x304
> +#define HSP_INT_IR_FULL_SHIFT 8
> +#define HSP_INT_IR_FULL_MASK 0xff
> +
> #define HSP_INT_DIMENSIONING 0x380
> #define HSP_nSM_SHIFT 0
> #define HSP_nSS_SHIFT 4
> @@ -34,6 +42,9 @@
> #define HSP_DB_RAW 0x8
> #define HSP_DB_PENDING 0xc
>
> +#define HSP_SM_SHRD_MBOX 0x0
> +#define HSP_SM_SHRD_MBOX_FULL BIT(31)
> +
> #define HSP_DB_CCPLEX 1
> #define HSP_DB_BPMP 3
> #define HSP_DB_MAX 7
> @@ -68,6 +79,18 @@ struct tegra_hsp_db_map {
> unsigned int index;
> };
>
> +struct tegra_hsp_mailbox {
> + struct tegra_hsp_channel channel;
> + unsigned int index;
> + bool sending;
> +};
> +
> +static inline struct tegra_hsp_mailbox *
> +channel_to_mailbox(struct tegra_hsp_channel *channel)
> +{
> + return container_of(channel, struct tegra_hsp_mailbox, channel);
> +}
> +
> struct tegra_hsp_soc {
> const struct tegra_hsp_db_map *map;
> };
> @@ -77,6 +100,7 @@ struct tegra_hsp {
> struct mbox_controller mbox;
> void __iomem *regs;
> unsigned int doorbell_irq;
> + unsigned int shared_irq;
> unsigned int num_sm;
> unsigned int num_as;
> unsigned int num_ss;
> @@ -85,6 +109,7 @@ struct tegra_hsp {
> spinlock_t lock;
>
> struct list_head doorbells;
> + struct tegra_hsp_mailbox *mailboxes;
> };
>
> static inline struct tegra_hsp *
> @@ -189,6 +214,33 @@ static irqreturn_t tegra_hsp_doorbell_irq(int irq, void *data)
> return IRQ_HANDLED;
> }
>
> +static irqreturn_t tegra_hsp_shared_irq(int irq, void *data)
> +{
> + struct tegra_hsp_mailbox *mb;
> + struct tegra_hsp *hsp = data;
> + unsigned long bit, mask;
> + u32 value;
> +
> + mask = tegra_hsp_readl(hsp, HSP_INT_IR);
> + /* Only interested in FULL interrupts */
> + mask = (mask >> HSP_INT_IR_FULL_SHIFT) & HSP_INT_IR_FULL_MASK;
> +
> + for_each_set_bit(bit, &mask, 8) {
> + mb = &hsp->mailboxes[bit];
> +
> + if (!mb->sending) {
> + value = tegra_hsp_channel_readl(&mb->channel,
> + HSP_SM_SHRD_MBOX);
> + value &= ~HSP_SM_SHRD_MBOX_FULL;
> + mbox_chan_received_data(mb->channel.chan, &value);
> + tegra_hsp_channel_writel(&mb->channel, value,
> + HSP_SM_SHRD_MBOX);
> + }
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> static struct tegra_hsp_channel *
> tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
> unsigned int master, unsigned int index)
> @@ -277,14 +329,57 @@ static void tegra_hsp_doorbell_shutdown(struct tegra_hsp_doorbell *db)
> spin_unlock_irqrestore(&hsp->lock, flags);
> }
>
> +static int tegra_hsp_mailbox_startup(struct tegra_hsp_mailbox *mb)
> +{
> + struct tegra_hsp *hsp = mb->channel.hsp;
> + u32 value;
> +
> + mb->channel.chan->txdone_method = TXDONE_BY_BLOCK;
> +
> + /* Route FULL interrupt to external IRQ 0 */
> + value = tegra_hsp_readl(hsp, HSP_INT0_IE);
> + value |= BIT(mb->index + 8);
Ideally this '8' should be defined as something like HSP_SM_FULL_IRQ_BASE.
> + tegra_hsp_writel(hsp, value, HSP_INT0_IE);
> +
> + return 0;
> +}
> +
> +static int tegra_hsp_mailbox_shutdown(struct tegra_hsp_mailbox *mb)
> +{
> + struct tegra_hsp *hsp = mb->channel.hsp;
> + u32 value;
> +
> + value = tegra_hsp_readl(hsp, HSP_INT0_IE);
> + value &= ~BIT(mb->index + 8);
> + tegra_hsp_writel(hsp, value, HSP_INT0_IE);
> +
> + return 0;
> +}
> +
> static int tegra_hsp_send_data(struct mbox_chan *chan, void *data)
> {
> struct tegra_hsp_channel *channel = chan->con_priv;
> + struct tegra_hsp_mailbox *mailbox;
> + uint32_t value;
>
> switch (channel->type) {
> case TEGRA_HSP_MBOX_TYPE_DB:
> tegra_hsp_channel_writel(channel, 1, HSP_DB_TRIGGER);
> return 0;
> +
> + case TEGRA_HSP_MBOX_TYPE_SM:
> + mailbox = channel_to_mailbox(channel);
> + mailbox->sending = true;
> +
> + value = *(uint32_t *)data;
> + /* Mark mailbox full */
> + value |= HSP_SM_SHRD_MBOX_FULL;
> +
> + tegra_hsp_channel_writel(channel, value, HSP_SM_SHRD_MBOX);
> +
> + return readl_poll_timeout(
> + channel->regs + HSP_SM_SHRD_MBOX, value,
> + !(value & HSP_SM_SHRD_MBOX_FULL), 0, 10000);
> }
>
> return -EINVAL;
> @@ -297,6 +392,8 @@ static int tegra_hsp_startup(struct mbox_chan *chan)
> switch (channel->type) {
> case TEGRA_HSP_MBOX_TYPE_DB:
> return tegra_hsp_doorbell_startup(channel_to_doorbell(channel));
> + case TEGRA_HSP_MBOX_TYPE_SM:
> + return tegra_hsp_mailbox_startup(channel_to_mailbox(channel));
> }
>
> return -EINVAL;
> @@ -310,6 +407,9 @@ static void tegra_hsp_shutdown(struct mbox_chan *chan)
> case TEGRA_HSP_MBOX_TYPE_DB:
> tegra_hsp_doorbell_shutdown(channel_to_doorbell(channel));
> break;
> + case TEGRA_HSP_MBOX_TYPE_SM:
> + tegra_hsp_mailbox_shutdown(channel_to_mailbox(channel));
> + break;
> }
> }
>
> @@ -363,7 +463,16 @@ static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
>
> switch (type) {
> case TEGRA_HSP_MBOX_TYPE_DB:
> - return tegra_hsp_doorbell_xlate(hsp, param);
> + if (hsp->doorbell_irq)
> + return tegra_hsp_doorbell_xlate(hsp, param);
> + else
> + return ERR_PTR(-EINVAL);
> +
> + case TEGRA_HSP_MBOX_TYPE_SM:
> + if (hsp->shared_irq && param < hsp->num_sm)
> + return hsp->mailboxes[param].channel.chan;
> + else
> + return ERR_PTR(-EINVAL);
>
> default:
> return ERR_PTR(-EINVAL);
> @@ -402,6 +511,31 @@ static int tegra_hsp_add_doorbells(struct tegra_hsp *hsp)
> return 0;
> }
>
> +static int tegra_hsp_add_mailboxes(struct tegra_hsp *hsp, struct device *dev)
> +{
> + int i;
> +
> + hsp->mailboxes = devm_kcalloc(dev, hsp->num_sm, sizeof(*hsp->mailboxes),
> + GFP_KERNEL);
> + if (!hsp->mailboxes)
> + return -ENOMEM;
> +
> + for (i = 0; i < hsp->num_sm; i++) {
> + struct tegra_hsp_mailbox *mb = &hsp->mailboxes[i];
> +
> + mb->index = i;
> + mb->sending = false;
> +
> + mb->channel.hsp = hsp;
> + mb->channel.type = TEGRA_HSP_MBOX_TYPE_SM;
> + mb->channel.regs = hsp->regs + SZ_64K + i * SZ_32K;
> + mb->channel.chan = &hsp->mbox.chans[i];
> + mb->channel.chan->con_priv = &mb->channel;
> + }
> +
> + return 0;
> +}
> +
> static int tegra_hsp_probe(struct platform_device *pdev)
> {
> struct tegra_hsp *hsp;
> @@ -430,14 +564,15 @@ static int tegra_hsp_probe(struct platform_device *pdev)
> hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK;
>
> err = platform_get_irq_byname(pdev, "doorbell");
> - if (err < 0) {
> - dev_err(&pdev->dev, "failed to get doorbell IRQ: %d\n", err);
> - return err;
> - }
> + if (err >= 0)
> + hsp->doorbell_irq = err;
>
> - hsp->doorbell_irq = err;
> + err = platform_get_irq_byname(pdev, "shared0");
> + if (err >= 0)
> + hsp->shared_irq = err;
>
> hsp->mbox.of_xlate = of_tegra_hsp_xlate;
> + /* First nSM are reserved for mailboxes */
> hsp->mbox.num_chans = 32;
> hsp->mbox.dev = &pdev->dev;
> hsp->mbox.txdone_irq = false;
> @@ -450,10 +585,22 @@ static int tegra_hsp_probe(struct platform_device *pdev)
> if (!hsp->mbox.chans)
> return -ENOMEM;
>
> - err = tegra_hsp_add_doorbells(hsp);
> - if (err < 0) {
> - dev_err(&pdev->dev, "failed to add doorbells: %d\n", err);
> - return err;
> + if (hsp->doorbell_irq) {
> + err = tegra_hsp_add_doorbells(hsp);
> + if (err < 0) {
> + dev_err(&pdev->dev, "failed to add doorbells: %d\n",
> + err);
> + return err;
> + }
> + }
> +
> + if (hsp->shared_irq) {
> + err = tegra_hsp_add_mailboxes(hsp, &pdev->dev);
> + if (err < 0) {
> + dev_err(&pdev->dev, "failed to add mailboxes: %d\n",
> + err);
> + goto remove_doorbells;
> + }
> }
>
> platform_set_drvdata(pdev, hsp);
> @@ -461,20 +608,42 @@ static int tegra_hsp_probe(struct platform_device *pdev)
> err = mbox_controller_register(&hsp->mbox);
> if (err) {
> dev_err(&pdev->dev, "failed to register mailbox: %d\n", err);
> - tegra_hsp_remove_doorbells(hsp);
> - return err;
> + goto remove_doorbells;
> }
>
> - err = devm_request_irq(&pdev->dev, hsp->doorbell_irq,
> - tegra_hsp_doorbell_irq, IRQF_NO_SUSPEND,
> - dev_name(&pdev->dev), hsp);
> - if (err < 0) {
> - dev_err(&pdev->dev, "failed to request doorbell IRQ#%u: %d\n",
> - hsp->doorbell_irq, err);
> - return err;
> + if (hsp->doorbell_irq) {
> + err = devm_request_irq(&pdev->dev, hsp->doorbell_irq,
> + tegra_hsp_doorbell_irq, IRQF_NO_SUSPEND,
> + dev_name(&pdev->dev), hsp);
> + if (err < 0) {
> + dev_err(&pdev->dev,
> + "failed to request doorbell IRQ#%u: %d\n",
> + hsp->doorbell_irq, err);
> + goto unregister_mbox_controller;
> + }
> + }
> +
> + if (hsp->shared_irq) {
> + err = devm_request_irq(&pdev->dev, hsp->shared_irq,
> + tegra_hsp_shared_irq, 0,
> + dev_name(&pdev->dev), hsp);
> + if (err < 0) {
> + dev_err(&pdev->dev,
> + "failed to request shared0 IRQ%u: %d\n",
> + hsp->shared_irq, err);
> + goto unregister_mbox_controller;
> + }
> }
>
> return 0;
> +
> +unregister_mbox_controller:
> + mbox_controller_unregister(&hsp->mbox);
> +remove_doorbells:
> + if (hsp->doorbell_irq)
> + tegra_hsp_remove_doorbells(hsp);
This bit looks like it should have been a separate patch to fix the
clean-up if probe fails. However, unless there is a reason to re-spin
the series, probably OK.
> +
> + return err;
> }
>
> static int tegra_hsp_remove(struct platform_device *pdev)
> @@ -482,7 +651,8 @@ static int tegra_hsp_remove(struct platform_device *pdev)
> struct tegra_hsp *hsp = platform_get_drvdata(pdev);
>
> mbox_controller_unregister(&hsp->mbox);
> - tegra_hsp_remove_doorbells(hsp);
> + if (hsp->doorbell_irq)
> + tegra_hsp_remove_doorbells(hsp);
>
> return 0;
> }
>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* KVM guest sometimes failed to boot because of kernel stack overflow if KPTI is enabled on a hisilicon ARM64 platform.
From: James Morse @ 2018-06-21 8:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5B2A7FE1.5040607@hisilicon.com>
Hi Will, Wei,
On 20/06/18 17:25, Wei Xu wrote:
> On 2018/6/20 23:54, James Morse wrote:
> I have disabled CONFIG_ARM64_RAS_EXTN and reverted that commit.
> But I still got the stack overflow issue sometimes.
> Do you have more hint?
> The log is as below:
> ??? [??? 0.000000] Booting Linux on physical CPU 0x0000000000 [0x480fd010]
> ??? [??? 0.000000] Linux version 4.17.0-45865-g2b31fe7-dirty
Could you reproduce this with v4.17? This says there are ~45,000 extra patches,
and un-committed changes. None of the hashes so far have been commits in
mainline, so we have no idea what this tree is.
> (joyx at Turing-Arch-b) (gcc version 4.9.1 20140505 (prerelease) (crosstool-NG
> linaro-1.13.1-4.9-2014.05 - Linaro GCC 4.9-2014.05)) #10 SMP PREEMPT Wed Jun 20
> 23:59:05 CST 2018
> ??? [??? 0.000000] CPU0: using LPI pending table @0x000000007d860000
> ??? [??? 0.000000] GIC: PPI11 is secure or misconfigured
> ??? [??? 0.000000] arch_timer: WARNING: Invalid trigger for IRQ3, assuming level
> low
> ??? [??? 0.000000] arch_timer: WARNING: Please fix your firmware
> ??? [??? 0.000000] arch_timer: cp15 timer(s) running at 100.00MHz (virt).
(No idea what these mean, but I doubt they are relevant)
> ??? [??? 0.042421] Insufficient stack space to handle exception!
> ??? [??? 0.042423] ESR: 0x96000046 -- DABT (current EL)
> ??? [??? 0.043730] FAR: 0xffff0000093a80e0
> ??? [??? 0.044714] Task stack: [0xffff0000093a8000..0xffff0000093ac000]
This was a level 2 translation fault on a write, to an address that is within
the stack....
> ??? [??? 0.051113] IRQ stack: [0xffff000008000000..0xffff000008004000]
> ??? [??? 0.057610] Overflow stack: [0xffff80003efce2f0..0xffff80003efcf2f0]
> ??? [??? 0.064003] CPU: 0 PID: 12 Comm: migration/0 Not tainted
> 4.17.0-45865-g2b31fe7-dirty #10
> ??? [??? 0.072201] Hardware name: linux,dummy-virt (DT)
> ??? [??? 0.076797] pstate: 604003c5 (nZCv DAIF +PAN -UAO)
> ??? [??? 0.081727] pc : el1_sync+0x0/0xb0
... from the vectors.
> ??? [??? 0.085217] lr : kpti_install_ng_mappings+0x120/0x214
What I think is happening is: we come out of the kpti idmap with the stack
unmapped. Shortly after we access the stack, which faults. el1_sync faults as
well when it tries to push the registers to the stack, and we keep going until
we overflow the stack.
I can't reproduce this with kvmtool or qemu in the model.
Thanks,
James
^ permalink raw reply
* [PATCH v3 09/14] ASoC: pxa: remove the dmaengine compat need
From: Robert Jarzmik @ 2018-06-21 8:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1984a4a7-e33b-6349-31f3-6f85ff1582b8@zonque.org>
Daniel Mack <daniel@zonque.org> writes:
> Hi Mark,
>
> I prepared a series of patches for 4.18 that conflict with this one. Instead of
> letting other people resolve this down the road, I'd prefer if this one went
> through the ASoC tree, if you don't mind.
>
> I've talked to Robert off-list, and he's fine with this approach.
That's right.
I'll tentativaly queue this patch to my pxa/for-next tree. As soon as I hear
that Mark queued it up in his tree, I'll drop it from mine.
Cheers.
--
Robert
^ permalink raw reply
* [PATCH 1/9] CHROMIUM: v4l: Add H264 low-level decoder API compound controls.
From: Paul Kocialkowski @ 2018-06-21 8:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180613140714.1686-2-maxime.ripard@bootlin.com>
Hi,
On Wed, 2018-06-13 at 16:07 +0200, Maxime Ripard wrote:
> From: Pawel Osciak <posciak@chromium.org>
>
> Signed-off-by: Pawel Osciak <posciak@chromium.org>
> Reviewed-by: Wu-cheng Li <wuchengli@chromium.org>
> Tested-by: Tomasz Figa <tfiga@chromium.org>
> [rebase44(groeck): include linux/types.h in v4l2-controls.h]
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
> drivers/media/v4l2-core/v4l2-ctrls.c | 42 +++++++
> include/media/v4l2-ctrls.h | 10 ++
> include/uapi/linux/v4l2-controls.h | 164 +++++++++++++++++++++++++++
> include/uapi/linux/videodev2.h | 11 ++
> 4 files changed, 227 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> index cdf860c8e3d8..1f63c725bad1 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -807,6 +807,11 @@ const char *v4l2_ctrl_get_name(u32 id)
> case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers";
> case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
> return "H264 Set QP Value for HC Layers";
> + case V4L2_CID_MPEG_VIDEO_H264_SPS: return "H264 SPS";
> + case V4L2_CID_MPEG_VIDEO_H264_PPS: return "H264 PPS";
> + case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX: return "H264 Scaling Matrix";
> + case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAM: return "H264 Slice Parameters";
The MPEG2 fashion of this control is called
V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_HEADER and it would be good to have
consistency between both.
I think having a _SLICE_PARAMS suffix for both (instead of _SLICE_HEADER
for MPEG2 and _SLICE_PARAM for H264) would make the most sense.
> + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAM: return "H264 Decode Parameters";
Same here, I think having a _DECODE_PARAMS suffix instead would be best.
Cheers,
Paul
> case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value";
> case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value";
> case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value";
> @@ -1272,6 +1277,21 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
> case V4L2_CID_RDS_TX_ALT_FREQS:
> *type = V4L2_CTRL_TYPE_U32;
> break;
> + case V4L2_CID_MPEG_VIDEO_H264_SPS:
> + *type = V4L2_CTRL_TYPE_H264_SPS;
> + break;
> + case V4L2_CID_MPEG_VIDEO_H264_PPS:
> + *type = V4L2_CTRL_TYPE_H264_PPS;
> + break;
> + case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX:
> + *type = V4L2_CTRL_TYPE_H264_SCALING_MATRIX;
> + break;
> + case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAM:
> + *type = V4L2_CTRL_TYPE_H264_SLICE_PARAM;
> + break;
> + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAM:
> + *type = V4L2_CTRL_TYPE_H264_DECODE_PARAM;
> + break;
> case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
> *type = V4L2_CTRL_TYPE_MPEG2_FRAME_HDR;
> break;
> @@ -1598,6 +1618,13 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
> case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
> return 0;
>
> + case V4L2_CTRL_TYPE_H264_SPS:
> + case V4L2_CTRL_TYPE_H264_PPS:
> + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
> + case V4L2_CTRL_TYPE_H264_SLICE_PARAM:
> + case V4L2_CTRL_TYPE_H264_DECODE_PARAM:
> + return 0;
> +
> default:
> return -EINVAL;
> }
> @@ -2172,6 +2199,21 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
> case V4L2_CTRL_TYPE_U32:
> elem_size = sizeof(u32);
> break;
> + case V4L2_CTRL_TYPE_H264_SPS:
> + elem_size = sizeof(struct v4l2_ctrl_h264_sps);
> + break;
> + case V4L2_CTRL_TYPE_H264_PPS:
> + elem_size = sizeof(struct v4l2_ctrl_h264_pps);
> + break;
> + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
> + elem_size = sizeof(struct v4l2_ctrl_h264_scaling_matrix);
> + break;
> + case V4L2_CTRL_TYPE_H264_SLICE_PARAM:
> + elem_size = sizeof(struct v4l2_ctrl_h264_slice_param);
> + break;
> + case V4L2_CTRL_TYPE_H264_DECODE_PARAM:
> + elem_size = sizeof(struct v4l2_ctrl_h264_decode_param);
> + break;
> case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
> elem_size = sizeof(struct v4l2_ctrl_mpeg2_frame_hdr);
> break;
> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
> index 963c37b02363..9c223793a16a 100644
> --- a/include/media/v4l2-ctrls.h
> +++ b/include/media/v4l2-ctrls.h
> @@ -41,6 +41,11 @@ struct poll_table_struct;
> * @p_u16: Pointer to a 16-bit unsigned value.
> * @p_u32: Pointer to a 32-bit unsigned value.
> * @p_char: Pointer to a string.
> + * @p_h264_sps: Pointer to a struct v4l2_ctrl_h264_sps.
> + * @p_h264_pps: Pointer to a struct v4l2_ctrl_h264_pps.
> + * @p_h264_scal_mtrx: Pointer to a struct v4l2_ctrl_h264_scaling_matrix.
> + * @p_h264_slice_param: Pointer to a struct v4l2_ctrl_h264_slice_param.
> + * @p_h264_decode_param: Pointer to a struct v4l2_ctrl_h264_decode_param.
> * @p: Pointer to a compound value.
> */
> union v4l2_ctrl_ptr {
> @@ -50,6 +55,11 @@ union v4l2_ctrl_ptr {
> u16 *p_u16;
> u32 *p_u32;
> char *p_char;
> + struct v4l2_ctrl_h264_sps *p_h264_sps;
> + struct v4l2_ctrl_h264_pps *p_h264_pps;
> + struct v4l2_ctrl_h264_scaling_matrix *p_h264_scal_mtrx;
> + struct v4l2_ctrl_h264_slice_param *p_h264_slice_param;
> + struct v4l2_ctrl_h264_decode_param *p_h264_decode_param;
> void *p;
> };
>
> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> index 23da8bfa7e6f..ac307c59683c 100644
> --- a/include/uapi/linux/v4l2-controls.h
> +++ b/include/uapi/linux/v4l2-controls.h
> @@ -50,6 +50,8 @@
> #ifndef __LINUX_V4L2_CONTROLS_H
> #define __LINUX_V4L2_CONTROLS_H
>
> +#include <linux/types.h>
> +
> /* Control classes */
> #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */
> #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */
> @@ -531,6 +533,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type {
> };
> #define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER (V4L2_CID_MPEG_BASE+381)
> #define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP (V4L2_CID_MPEG_BASE+382)
> +#define V4L2_CID_MPEG_VIDEO_H264_SPS (V4L2_CID_MPEG_BASE+383)
> +#define V4L2_CID_MPEG_VIDEO_H264_PPS (V4L2_CID_MPEG_BASE+384)
> +#define V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (V4L2_CID_MPEG_BASE+385)
> +#define V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAM (V4L2_CID_MPEG_BASE+386)
> +#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAM (V4L2_CID_MPEG_BASE+387)
> +
> #define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (V4L2_CID_MPEG_BASE+400)
> #define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP (V4L2_CID_MPEG_BASE+401)
> #define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP (V4L2_CID_MPEG_BASE+402)
> @@ -1078,6 +1086,162 @@ enum v4l2_detect_md_mode {
> #define V4L2_CID_DETECT_MD_THRESHOLD_GRID (V4L2_CID_DETECT_CLASS_BASE + 3)
> #define V4L2_CID_DETECT_MD_REGION_GRID (V4L2_CID_DETECT_CLASS_BASE + 4)
>
> +/* Complex controls */
> +
> +#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01
> +#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02
> +#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04
> +#define V4L2_H264_SPS_CONSTRAINT_SET3_FLAG 0x08
> +#define V4L2_H264_SPS_CONSTRAINT_SET4_FLAG 0x10
> +#define V4L2_H264_SPS_CONSTRAINT_SET5_FLAG 0x20
> +
> +#define V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE 0x01
> +#define V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS 0x02
> +#define V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO 0x04
> +#define V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED 0x08
> +#define V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY 0x10
> +#define V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD 0x20
> +#define V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE 0x40
> +struct v4l2_ctrl_h264_sps {
> + __u8 profile_idc;
> + __u8 constraint_set_flags;
> + __u8 level_idc;
> + __u8 seq_parameter_set_id;
> + __u8 chroma_format_idc;
> + __u8 bit_depth_luma_minus8;
> + __u8 bit_depth_chroma_minus8;
> + __u8 log2_max_frame_num_minus4;
> + __u8 pic_order_cnt_type;
> + __u8 log2_max_pic_order_cnt_lsb_minus4;
> + __s32 offset_for_non_ref_pic;
> + __s32 offset_for_top_to_bottom_field;
> + __u8 num_ref_frames_in_pic_order_cnt_cycle;
> + __s32 offset_for_ref_frame[255];
> + __u8 max_num_ref_frames;
> + __u16 pic_width_in_mbs_minus1;
> + __u16 pic_height_in_map_units_minus1;
> + __u8 flags;
> +};
> +
> +#define V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE 0x0001
> +#define V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT 0x0002
> +#define V4L2_H264_PPS_FLAG_WEIGHTED_PRED 0x0004
> +#define V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT 0x0008
> +#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010
> +#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020
> +#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040
> +#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080
> +struct v4l2_ctrl_h264_pps {
> + __u8 pic_parameter_set_id;
> + __u8 seq_parameter_set_id;
> + __u8 num_slice_groups_minus1;
> + __u8 num_ref_idx_l0_default_active_minus1;
> + __u8 num_ref_idx_l1_default_active_minus1;
> + __u8 weighted_bipred_idc;
> + __s8 pic_init_qp_minus26;
> + __s8 pic_init_qs_minus26;
> + __s8 chroma_qp_index_offset;
> + __s8 second_chroma_qp_index_offset;
> + __u8 flags;
> +};
> +
> +struct v4l2_ctrl_h264_scaling_matrix {
> + __u8 scaling_list_4x4[6][16];
> + __u8 scaling_list_8x8[6][64];
> +};
> +
> +struct v4l2_h264_weight_factors {
> + __s8 luma_weight[32];
> + __s8 luma_offset[32];
> + __s8 chroma_weight[32][2];
> + __s8 chroma_offset[32][2];
> +};
> +
> +struct v4l2_h264_pred_weight_table {
> + __u8 luma_log2_weight_denom;
> + __u8 chroma_log2_weight_denom;
> + struct v4l2_h264_weight_factors weight_factors[2];
> +};
> +
> +enum v4l2_h264_slice_type {
> + V4L2_H264_SLICE_TYPE_P = 0,
> + V4L2_H264_SLICE_TYPE_B = 1,
> + V4L2_H264_SLICE_TYPE_I = 2,
> + V4L2_H264_SLICE_TYPE_SP = 3,
> + V4L2_H264_SLICE_TYPE_SI = 4,
> +};
>
> +#define V4L2_SLICE_FLAG_FIELD_PIC 0x01
> +#define V4L2_SLICE_FLAG_BOTTOM_FIELD 0x02
> +#define V4L2_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04
> +#define V4L2_SLICE_FLAG_SP_FOR_SWITCH 0x08
> +struct v4l2_ctrl_h264_slice_param {
> + /* Size in bytes, including header */
> + __u32 size;
> + /* Offset in bits to slice_data() from the beginning of this slice. */
> + __u32 header_bit_size;
> +
> + __u16 first_mb_in_slice;
> + enum v4l2_h264_slice_type slice_type;
> + __u8 pic_parameter_set_id;
> + __u8 colour_plane_id;
> + __u16 frame_num;
> + __u16 idr_pic_id;
> + __u16 pic_order_cnt_lsb;
> + __s32 delta_pic_order_cnt_bottom;
> + __s32 delta_pic_order_cnt0;
> + __s32 delta_pic_order_cnt1;
> + __u8 redundant_pic_cnt;
> +
> + struct v4l2_h264_pred_weight_table pred_weight_table;
> + /* Size in bits of dec_ref_pic_marking() syntax element. */
> + __u32 dec_ref_pic_marking_bit_size;
> + /* Size in bits of pic order count syntax. */
> + __u32 pic_order_cnt_bit_size;
> +
> + __u8 cabac_init_idc;
> + __s8 slice_qp_delta;
> + __s8 slice_qs_delta;
> + __u8 disable_deblocking_filter_idc;
> + __s8 slice_alpha_c0_offset_div2;
> + __s8 slice_beta_offset_div2;
> + __u32 slice_group_change_cycle;
> +
> + __u8 num_ref_idx_l0_active_minus1;
> + __u8 num_ref_idx_l1_active_minus1;
> + /* Entries on each list are indices
> + * into v4l2_ctrl_h264_decode_param.dpb[]. */
> + __u8 ref_pic_list0[32];
> + __u8 ref_pic_list1[32];
> +
> + __u8 flags;
> +};
> +
> +/* If not set, this entry is unused for reference. */
> +#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x01
> +#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x02
> +struct v4l2_h264_dpb_entry {
> + __u32 buf_index; /* v4l2_buffer index */
> + __u16 frame_num;
> + __u16 pic_num;
> + /* Note that field is indicated by v4l2_buffer.field */
> + __s32 top_field_order_cnt;
> + __s32 bottom_field_order_cnt;
> + __u8 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */
> +};
> +
> +struct v4l2_ctrl_h264_decode_param {
> + __u32 num_slices;
> + __u8 idr_pic_flag;
> + __u8 nal_ref_idc;
> + __s32 top_field_order_cnt;
> + __s32 bottom_field_order_cnt;
> + __u8 ref_pic_list_p0[32];
> + __u8 ref_pic_list_b0[32];
> + __u8 ref_pic_list_b1[32];
> + struct v4l2_h264_dpb_entry dpb[16];
> +};
> +
> struct v4l2_ctrl_mpeg2_frame_hdr {
> __u32 slice_len;
> __u32 slice_pos;
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 242a6bfa1440..4b4a1b25a0db 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -626,6 +626,7 @@ struct v4l2_pix_format {
> #define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
> #define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
> #define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
> +#define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */
> #define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */
> #define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES */
> #define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES */
> @@ -1589,6 +1590,11 @@ struct v4l2_ext_control {
> __u8 __user *p_u8;
> __u16 __user *p_u16;
> __u32 __user *p_u32;
> + struct v4l2_ctrl_h264_sps __user *p_h264_sps;
> + struct v4l2_ctrl_h264_pps __user *p_h264_pps;
> + struct v4l2_ctrl_h264_scaling_matrix __user *p_h264_scal_mtrx;
> + struct v4l2_ctrl_h264_slice_param __user *p_h264_slice_param;
> + struct v4l2_ctrl_h264_decode_param __user *p_h264_decode_param;
> struct v4l2_ctrl_mpeg2_frame_hdr __user *p_mpeg2_frame_hdr;
> void __user *ptr;
> };
> @@ -1635,6 +1641,11 @@ enum v4l2_ctrl_type {
> V4L2_CTRL_TYPE_U8 = 0x0100,
> V4L2_CTRL_TYPE_U16 = 0x0101,
> V4L2_CTRL_TYPE_U32 = 0x0102,
> + V4L2_CTRL_TYPE_H264_SPS = 0x0103,
> + V4L2_CTRL_TYPE_H264_PPS = 0x0104,
> + V4L2_CTRL_TYPE_H264_SCALING_MATRIX = 0x0105,
> + V4L2_CTRL_TYPE_H264_SLICE_PARAM = 0x0106,
> + V4L2_CTRL_TYPE_H264_DECODE_PARAM = 0x0107,
> V4L2_CTRL_TYPE_MPEG2_FRAME_HDR = 0x0109,
> };
>
--
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180621/ced8e9d4/attachment-0001.sig>
^ permalink raw reply
* [PATCH 1/1] arm64/mm: move {idmap_pg_dir,tramp_pg_dir,swapper_pg_dir} to .rodata section
From: James Morse @ 2018-06-21 8:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu_3Cfuq-qQuRHkYCB2uTPOK=KVeVh4OKmtu2MDYwfOtTA@mail.gmail.com>
Hi guys,
On 21/06/18 07:39, Ard Biesheuvel wrote:
> On 21 June 2018 at 04:51, Jun Yao <yaojun8558363@gmail.com> wrote:
>> On Wed, Jun 20, 2018 at 12:09:49PM +0200, Ard Biesheuvel wrote:
>>> On 20 June 2018 at 10:57, Jun Yao <yaojun8558363@gmail.com> wrote:
>>>> Move {idmap_pg_dir,tramp_pg_dir,swapper_pg_dir} to .rodata
>>>> section. And update the swapper_pg_dir by fixmap.
>>>>
>>>
>>> I think we may be able to get away with not mapping idmap_pg_dir and
>>> tramp_pg_dir at all.
>>
>> I think we need to move tramp_pg_dir to .rodata. The attacker can write
>> a block-mapping(AP=01) to tramp_pg_dir and then he can access kernel
>> memory.
> Why does it need to be mapped at all? When do we ever access it from the code?
(We would want to make its fixmap entry read-only too)
>>> As for swapper_pg_dir, it would indeed be nice if we could keep those
>>> mappings read-only most of the time, but I'm not sure how useful this
>>> is if we apply it to the root level only.
>>
>> The purpose of it is to make 'KSMA' harder, where an single arbitrary
>> write is used to add a block mapping to the page-tables, giving the
>> attacker full access to kernel memory. That's why we just apply it to
>> the root level only. If the attacker can arbitrary write multiple times,
>> I think it's hard to defend.
>>
>
> So the assumption is that the root level is more easy to find?
> Otherwise, I'm not sure I understand why being able to write a level 0
> entry is so harmful, given that we don't have block mappings at that
> level.
I think this thing assumes 3-level page tables with 39bit VA.
>>>> @@ -417,12 +421,22 @@ static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start,
>>>>
>>>> void __init mark_linear_text_alias_ro(void)
>>>> {
>>>> + size = (unsigned long)__init_begin - (unsigned long)swapper_pg_end;
>>>> + update_mapping_prot(__pa_symbol(swapper_pg_end),
>>>> + (unsigned long)lm_alias(swapper_pg_end),
>>>> + size, PAGE_KERNEL_RO);
>>>
>>> I don't think this is necessary. Even if some pages are freed, it
>>> doesn't harm to keep a read-only alias of them here since the new
>>> owner won't access them via this mapping anyway. So we can keep
>>> .rodata as a single region.
>>
>> To be honest, I didn't think of this issue at first. I later found a
>> problem when testing the code on qemu:
>
> OK, you're right. I missed the fact that this operates on the linear
> alias, not the kernel mapping itself.
>
> What I don't like is that we lose the ability to use block mappings
> for the entire .rodata section this way. Isn't it possible to move
> these pgdirs to the end of the .rodata segment, perhaps by using a
> separate input section name and placing that explicitly? We could even
> simply forget about freeing those pages, given that [on 4k pages] the
> benefit of freeing 12 KB of space is likely to get lost in the
> rounding noise anyway [segments are rounded up to 64 KB in size]
I assumed that to move swapper_pg_dir into the .rodata section we would need to
break it up. Today its ~3 levels, which we setup in head.S, then do a dance in
paging_init() so that swapper_pg_dir is always the top level.
We could generate all leves of the 'init_pg_dir' in the __initdata section, then
copy only the top level into swapper_pg_dir into the rodata section during
paging_init().
Thanks,
James
^ permalink raw reply
* KVM guest sometimes failed to boot because of kernel stack overflow if KPTI is enabled on a hisilicon ARM64 platform.
From: Marc Zyngier @ 2018-06-21 9:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e701eaa8-dcb9-777c-2211-67ee27b43acb@arm.com>
On 21/06/18 09:38, James Morse wrote:
>> (joyx at Turing-Arch-b) (gcc version 4.9.1 20140505 (prerelease) (crosstool-NG
>> linaro-1.13.1-4.9-2014.05 - Linaro GCC 4.9-2014.05)) #10 SMP PREEMPT Wed Jun 20
>> 23:59:05 CST 2018
>
>> ??? [??? 0.000000] CPU0: using LPI pending table @0x000000007d860000
>> ??? [??? 0.000000] GIC: PPI11 is secure or misconfigured
>> ??? [??? 0.000000] arch_timer: WARNING: Invalid trigger for IRQ3, assuming level
>> low
>> ??? [??? 0.000000] arch_timer: WARNING: Please fix your firmware
>> ??? [??? 0.000000] arch_timer: cp15 timer(s) running at 100.00MHz (virt).
>
> (No idea what these mean, but I doubt they are relevant)
Old (and buggy) QEMU. Nothing to worry about, the kernel (and the vgic)
will do the right thing. A modern QEMU presents the guest with a fixed
DT, removing the warning altogether.
Nothing to do with the issue at hand anyway.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH V4 0/4] add iwdg2 support for stm32mp157c
From: Ludovic Barre @ 2018-06-21 9:02 UTC (permalink / raw)
To: linux-arm-kernel
From: Ludovic Barre <ludovic.barre@st.com>
This patch series updates stm32_iwdg driver to manage pclk
clock by compatible. stm32mp1 requires a pclk clock.
v4:
-dt-bindings: split and review
v3:
-remove stm32_iwdg_config structure, just assign the
boolean directly to .dat
Ludovic Barre (4):
dt-bindings: watchdog: add stm32mp1 support
watchdog: stm32: add pclk feature for stm32mp1
ARM: dts: stm32: add iwdg2 support for stm32mp157c
ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1
.../devicetree/bindings/watchdog/st,stm32-iwdg.txt | 13 ++-
arch/arm/boot/dts/stm32mp157c-ed1.dts | 5 +
arch/arm/boot/dts/stm32mp157c.dtsi | 8 ++
drivers/watchdog/stm32_iwdg.c | 116 +++++++++++++--------
4 files changed, 97 insertions(+), 45 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH V4 1/4] dt-bindings: watchdog: add stm32mp1 support
From: Ludovic Barre @ 2018-06-21 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529571737-3552-1-git-send-email-ludovic.Barre@st.com>
From: Ludovic Barre <ludovic.barre@st.com>
This patch adds support of stm32mp1.
stm32mp1 requires 2 clocks lsi and pclk.
Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
---
.../devicetree/bindings/watchdog/st,stm32-iwdg.txt | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
index cc13b10a..d8f4430 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,9 +2,15 @@ STM32 Independent WatchDoG (IWDG)
---------------------------------
Required properties:
-- compatible: "st,stm32-iwdg"
-- reg: physical base address and length of the registers set for the device
-- clocks: must contain a single entry describing the clock input
+- compatible: Should be either:
+ - "st,stm32-iwdg"
+ - "st,stm32mp1-iwdg"
+- reg: Physical base address and length of the registers set for the device
+- clocks: Reference to the clock entry lsi. Additional pclk clock entry
+ is required only for st,stm32mp1-iwdg.
+- clock-names: Name of the clocks used.
+ "lsi" for st,stm32-iwdg
+ "lsi", "pclk" for st,stm32mp1-iwdg
Optional Properties:
- timeout-sec: Watchdog timeout value in seconds.
@@ -15,5 +21,6 @@ iwdg: watchdog at 40003000 {
compatible = "st,stm32-iwdg";
reg = <0x40003000 0x400>;
clocks = <&clk_lsi>;
+ clock-names = "lsi";
timeout-sec = <32>;
};
--
2.7.4
^ permalink raw reply related
* [PATCH V4 2/4] watchdog: stm32: add pclk feature for stm32mp1
From: Ludovic Barre @ 2018-06-21 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529571737-3552-1-git-send-email-ludovic.Barre@st.com>
From: Ludovic Barre <ludovic.barre@st.com>
This patch adds compatible data to manage pclk clock by
compatible. Adds stm32mp1 support which requires pclk clock.
Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
---
drivers/watchdog/stm32_iwdg.c | 116 +++++++++++++++++++++++++++---------------
1 file changed, 74 insertions(+), 42 deletions(-)
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index c97ad56..e00e3b3 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
#include <linux/clk.h>
#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
@@ -54,11 +55,15 @@
#define TIMEOUT_US 100000
#define SLEEP_US 1000
+#define HAS_PCLK true
+
struct stm32_iwdg {
struct watchdog_device wdd;
void __iomem *regs;
- struct clk *clk;
+ struct clk *clk_lsi;
+ struct clk *clk_pclk;
unsigned int rate;
+ bool has_pclk;
};
static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -133,6 +138,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device *wdd,
return 0;
}
+static int stm32_iwdg_clk_init(struct platform_device *pdev,
+ struct stm32_iwdg *wdt)
+{
+ u32 ret;
+
+ wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
+ if (IS_ERR(wdt->clk_lsi)) {
+ dev_err(&pdev->dev, "Unable to get lsi clock\n");
+ return PTR_ERR(wdt->clk_lsi);
+ }
+
+ /* optional peripheral clock */
+ if (wdt->has_pclk) {
+ wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(wdt->clk_pclk)) {
+ dev_err(&pdev->dev, "Unable to get pclk clock\n");
+ return PTR_ERR(wdt->clk_pclk);
+ }
+
+ ret = clk_prepare_enable(wdt->clk_pclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
+ return ret;
+ }
+ }
+
+ ret = clk_prepare_enable(wdt->clk_lsi);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
+ clk_disable_unprepare(wdt->clk_pclk);
+ return ret;
+ }
+
+ wdt->rate = clk_get_rate(wdt->clk_lsi);
+
+ return 0;
+}
+
static const struct watchdog_info stm32_iwdg_info = {
.options = WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE |
@@ -147,49 +190,42 @@ static const struct watchdog_ops stm32_iwdg_ops = {
.set_timeout = stm32_iwdg_set_timeout,
};
+static const struct of_device_id stm32_iwdg_of_match[] = {
+ { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK },
+ { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK },
+ { /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
+
static int stm32_iwdg_probe(struct platform_device *pdev)
{
struct watchdog_device *wdd;
+ const struct of_device_id *match;
struct stm32_iwdg *wdt;
struct resource *res;
- void __iomem *regs;
- struct clk *clk;
int ret;
+ match = of_match_device(stm32_iwdg_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+
+ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+ if (!wdt)
+ return -ENOMEM;
+
+ wdt->has_pclk = match->data;
+
/* This is the timer base. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- regs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(regs)) {
+ wdt->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(wdt->regs)) {
dev_err(&pdev->dev, "Could not get resource\n");
- return PTR_ERR(regs);
+ return PTR_ERR(wdt->regs);
}
- clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "Unable to get clock\n");
- return PTR_ERR(clk);
- }
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- dev_err(&pdev->dev, "Unable to prepare clock %p\n", clk);
+ ret = stm32_iwdg_clk_init(pdev, wdt);
+ if (ret)
return ret;
- }
-
- /*
- * Allocate our watchdog driver data, which has the
- * struct watchdog_device nested within it.
- */
- wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
- if (!wdt) {
- ret = -ENOMEM;
- goto err;
- }
-
- /* Initialize struct stm32_iwdg. */
- wdt->regs = regs;
- wdt->clk = clk;
- wdt->rate = clk_get_rate(clk);
/* Initialize struct watchdog_device. */
wdd = &wdt->wdd;
@@ -217,7 +253,8 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
return 0;
err:
- clk_disable_unprepare(clk);
+ clk_disable_unprepare(wdt->clk_lsi);
+ clk_disable_unprepare(wdt->clk_pclk);
return ret;
}
@@ -227,23 +264,18 @@ static int stm32_iwdg_remove(struct platform_device *pdev)
struct stm32_iwdg *wdt = platform_get_drvdata(pdev);
watchdog_unregister_device(&wdt->wdd);
- clk_disable_unprepare(wdt->clk);
+ clk_disable_unprepare(wdt->clk_lsi);
+ clk_disable_unprepare(wdt->clk_pclk);
return 0;
}
-static const struct of_device_id stm32_iwdg_of_match[] = {
- { .compatible = "st,stm32-iwdg" },
- { /* end node */ }
-};
-MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
-
static struct platform_driver stm32_iwdg_driver = {
.probe = stm32_iwdg_probe,
.remove = stm32_iwdg_remove,
.driver = {
.name = "iwdg",
- .of_match_table = stm32_iwdg_of_match,
+ .of_match_table = of_match_ptr(stm32_iwdg_of_match),
},
};
module_platform_driver(stm32_iwdg_driver);
--
2.7.4
^ permalink raw reply related
* [PATCH V4 3/4] ARM: dts: stm32: add iwdg2 support for stm32mp157c
From: Ludovic Barre @ 2018-06-21 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529571737-3552-1-git-send-email-ludovic.Barre@st.com>
From: Ludovic Barre <ludovic.barre@st.com>
This patch adds independent watchdog support for stm32mp157c.
Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
---
arch/arm/boot/dts/stm32mp157c.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
index 7d17538..95cc166 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -784,6 +784,14 @@
status = "disabled";
};
+ iwdg2: watchdog at 5a002000 {
+ compatible = "st,stm32mp1-iwdg";
+ reg = <0x5a002000 0x400>;
+ clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+ clock-names = "pclk", "lsi";
+ status = "disabled";
+ };
+
usbphyc: usbphyc at 5a006000 {
#address-cells = <1>;
#size-cells = <0>;
--
2.7.4
^ permalink raw reply related
* [PATCH V4 4/4] ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1
From: Ludovic Barre @ 2018-06-21 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529571737-3552-1-git-send-email-ludovic.Barre@st.com>
From: Ludovic Barre <ludovic.barre@st.com>
This patch activates independent watchdog support for
stm32mp157c board.
Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
---
arch/arm/boot/dts/stm32mp157c-ed1.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index ae33653..8af263a 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -68,6 +68,11 @@
status = "okay";
};
+&iwdg2 {
+ timeout-sec = <32>;
+ status = "okay";
+};
+
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_a>;
--
2.7.4
^ permalink raw reply related
* [PATCH 2/9] media: cedrus: Add wrappers around container_of for our buffers
From: Paul Kocialkowski @ 2018-06-21 9:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180613140714.1686-3-maxime.ripard@bootlin.com>
Hi,
On Wed, 2018-06-13 at 16:07 +0200, Maxime Ripard wrote:
> The cedrus driver sub-classes the vb2_v4l2_buffer structure, but doesn't
> provide any function to wrap around the proper container_of call that needs
> to be duplicated in every calling site.
>
> Add wrappers to make sure its opaque to the users and they don't have to
> care anymore.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
> .../platform/sunxi/cedrus/sunxi_cedrus_common.h | 12 ++++++++++++
> .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.c | 4 ++--
> 2 files changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> index ee6883ef9cb7..b1ed1c8cb130 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> @@ -89,6 +89,18 @@ struct sunxi_cedrus_buffer {
> struct list_head list;
> };
>
> +static inline
I'm not a big fan of spreading the type qualifiers on two distinct lines
instead of having a longer single line (reminds me of the GNU coding
style a bit), but this is purely cosmetic.
Cheers,
Paul
> +struct sunxi_cedrus_buffer *vb2_v4l2_to_cedrus_buffer(const struct vb2_v4l2_buffer *p)
> +{
> + return container_of(p, struct sunxi_cedrus_buffer, vb);
> +}
> +
> +static inline
> +struct sunxi_cedrus_buffer *vb2_to_cedrus_buffer(const struct vb2_buffer *p)
> +{
> + return vb2_v4l2_to_cedrus_buffer(to_vb2_v4l2_buffer(p));
> +}
> +
> struct sunxi_cedrus_dev {
> struct v4l2_device v4l2_dev;
> struct video_device vfd;
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> index 5783bd985855..fc688a5c1ea3 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> @@ -108,8 +108,8 @@ static irqreturn_t sunxi_cedrus_ve_irq(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> - src_buffer = container_of(src_vb, struct sunxi_cedrus_buffer, vb);
> - dst_buffer = container_of(dst_vb, struct sunxi_cedrus_buffer, vb);
> + src_buffer = vb2_v4l2_to_cedrus_buffer(src_vb);
> + dst_buffer = vb2_v4l2_to_cedrus_buffer(dst_vb);
>
> /* First bit of MPEG_STATUS indicates success. */
> if (ctx->job_abort || !(status & 0x01))
--
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180621/33933c40/attachment.sig>
^ permalink raw reply
* [PATCH] ARM: hwmod: RTC: Don't assume lock/unlock will be called with irq enabled
From: Keerthy @ 2018-06-21 9:13 UTC (permalink / raw)
To: linux-arm-kernel
From: Dave Gerlach <d-gerlach@ti.com>
When the RTC lock and unlock functions were introduced it was likely
assumed that they would always be called from irq enabled context, hence
the use of local_irq_disable/enable. This is no longer true as the
RTC+DDR path makes a late call during the suspend path after irqs
have been disabled to enable the RTC hwmod which calls both unlock and
lock, leading to IRQs being reenabled through the local_irq_enable call
in omap_hwmod_rtc_lock call.
To avoid this change the local_irq_disable/enable to
local_irq_save/restore to ensure that from whatever context this is
called the proper IRQ configuration is maintained.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
arch/arm/mach-omap2/omap_hwmod_reset.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_reset.c b/arch/arm/mach-omap2/omap_hwmod_reset.c
index b68f9c0..d5ddba0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_reset.c
+++ b/arch/arm/mach-omap2/omap_hwmod_reset.c
@@ -92,11 +92,13 @@ static void omap_rtc_wait_not_busy(struct omap_hwmod *oh)
*/
void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
{
- local_irq_disable();
+ unsigned long flags;
+
+ local_irq_save(flags);
omap_rtc_wait_not_busy(oh);
omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG);
omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG);
- local_irq_enable();
+ local_irq_restore(flags);
}
/**
@@ -110,9 +112,11 @@ void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
*/
void omap_hwmod_rtc_lock(struct omap_hwmod *oh)
{
- local_irq_disable();
+ unsigned long flags;
+
+ local_irq_save(flags);
omap_rtc_wait_not_busy(oh);
omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG);
omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG);
- local_irq_enable();
+ local_irq_restore(flags);
}
--
1.9.1
^ permalink raw reply related
* [PATCH 3/9] media: cedrus: Add a macro to check for the validity of a control
From: Paul Kocialkowski @ 2018-06-21 9:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180613140714.1686-4-maxime.ripard@bootlin.com>
Hi,
On Wed, 2018-06-13 at 16:07 +0200, Maxime Ripard wrote:
> During our frame decoding setup, we need to check a number of controls to
> make sure that they are properly filled before trying to access them.
>
> It's not too bad with MPEG2 since there's just a single one, but with the
> upcoming increase of codecs, and the integration of more complex codecs,
> this logic will be duplicated a significant number of times. H264 for
> example uses 4 different controls.
>
> Add a macro that expands to the proper check in order to reduce the
> duplication.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
> .../platform/sunxi/cedrus/sunxi_cedrus_dec.c | 16 +++++++++-------
> 1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> index 8c92af34ebeb..c19acf9626c4 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> @@ -110,15 +110,16 @@ void sunxi_cedrus_device_run(void *priv)
>
> spin_lock_irqsave(&ctx->dev->irq_lock, flags);
>
> +#define CHECK_CONTROL(ctx, ctrl) \
> + if (!ctx->ctrls[(ctrl)]) { \
Although this was not introduced in this patch, I believe this approach
won't work since ctx->ctrls[i] is a pointer returned from
v4l2_ctrl_new_custom(hdl, &cfg, NULL), which will always be non-null
after calling cedrus_init_ctrls.
Perhaps checking ctx->ctrls[i].p_cur.p would be the right thing to
check, but I'm unsure about that.
> + v4l2_err(&(ctx)->dev->v4l2_dev, "Invalid " #ctrl " control\n"); \
> + (ctx)->job_abort = 1; \
> + goto unlock_complete; \
> + }
> +
> switch (ctx->vpu_src_fmt->fourcc) {
> case V4L2_PIX_FMT_MPEG2_FRAME:
> - if (!ctx->ctrls[SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR]) {
> - v4l2_err(&ctx->dev->v4l2_dev,
> - "Invalid MPEG2 frame header control\n");
> - ctx->job_abort = 1;
> - goto unlock_complete;
> - }
> -
> + CHECK_CONTROL(ctx, SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR);
> run.mpeg2.hdr = get_ctrl_ptr(ctx, SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR);
> sunxi_cedrus_mpeg2_setup(ctx, &run);
>
> @@ -128,6 +129,7 @@ void sunxi_cedrus_device_run(void *priv)
> default:
> ctx->job_abort = 1;
> }
Maybe add a newline here?
Cheers,
Paul
> +#undef CHECK_CONTROL
>
> unlock_complete:
> spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
--
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180621/b3b35974/attachment.sig>
^ permalink raw reply
* KVM guest sometimes failed to boot because of kernel stack overflow if KPTI is enabled on a hisilicon ARM64 platform.
From: Will Deacon @ 2018-06-21 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e701eaa8-dcb9-777c-2211-67ee27b43acb@arm.com>
On Thu, Jun 21, 2018 at 09:38:53AM +0100, James Morse wrote:
> On 20/06/18 17:25, Wei Xu wrote:
> > ??? [??? 0.042421] Insufficient stack space to handle exception!
> > ??? [??? 0.042423] ESR: 0x96000046 -- DABT (current EL)
> > ??? [??? 0.043730] FAR: 0xffff0000093a80e0
> > ??? [??? 0.044714] Task stack: [0xffff0000093a8000..0xffff0000093ac000]
>
> This was a level 2 translation fault on a write, to an address that is within
> the stack....
>
>
> > ??? [??? 0.051113] IRQ stack: [0xffff000008000000..0xffff000008004000]
> > ??? [??? 0.057610] Overflow stack: [0xffff80003efce2f0..0xffff80003efcf2f0]
> > ??? [??? 0.064003] CPU: 0 PID: 12 Comm: migration/0 Not tainted
> > 4.17.0-45865-g2b31fe7-dirty #10
> > ??? [??? 0.072201] Hardware name: linux,dummy-virt (DT)
>
> > ??? [??? 0.076797] pstate: 604003c5 (nZCv DAIF +PAN -UAO)
> > ??? [??? 0.081727] pc : el1_sync+0x0/0xb0
>
> ... from the vectors.
>
>
> > ??? [??? 0.085217] lr : kpti_install_ng_mappings+0x120/0x214
>
> What I think is happening is: we come out of the kpti idmap with the stack
> unmapped. Shortly after we access the stack, which faults. el1_sync faults as
> well when it tries to push the registers to the stack, and we keep going until
> we overflow the stack.
>
> I can't reproduce this with kvmtool or qemu in the model.
Hmm, one thing that occurs to me is that the kpti_install_ng_mappings()
code leaves the nG bit set in table entries, which is actually IGNORED in
the architecture.
Wei -- does the diff below help at all? Make sure you disable CONFIG_KASAN,
otherwise your kernel will take an age to boot.
Will
--->8
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 5f9a73a4452c..70d9e98467ca 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -272,8 +272,8 @@ ENTRY(idmap_kpti_install_ng_mappings)
add end_pgdp, cur_pgdp, #(PTRS_PER_PGD * 8)
do_pgd: __idmap_kpti_get_pgtable_ent pgd
tbnz pgd, #1, walk_puds
-next_pgd:
__idmap_kpti_put_pgtable_ent_ng pgd
+next_pgd:
skip_pgd:
add cur_pgdp, cur_pgdp, #8
cmp cur_pgdp, end_pgdp
@@ -302,8 +302,8 @@ walk_puds:
add end_pudp, cur_pudp, #(PTRS_PER_PUD * 8)
do_pud: __idmap_kpti_get_pgtable_ent pud
tbnz pud, #1, walk_pmds
-next_pud:
__idmap_kpti_put_pgtable_ent_ng pud
+next_pud:
skip_pud:
add cur_pudp, cur_pudp, 8
cmp cur_pudp, end_pudp
@@ -323,8 +323,8 @@ walk_pmds:
add end_pmdp, cur_pmdp, #(PTRS_PER_PMD * 8)
do_pmd: __idmap_kpti_get_pgtable_ent pmd
tbnz pmd, #1, walk_ptes
-next_pmd:
__idmap_kpti_put_pgtable_ent_ng pmd
+next_pmd:
skip_pmd:
add cur_pmdp, cur_pmdp, #8
cmp cur_pmdp, end_pmdp
^ permalink raw reply related
* [PATCH v2 6/8] serial: Add Tegra Combined UART driver
From: Jon Hunter @ 2018-06-21 9:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620122042.10950-7-mperttunen@nvidia.com>
On 20/06/18 13:20, Mikko Perttunen wrote:
> The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows
> multiplexing multiple "virtual UARTs" into a single hardware serial
> port. The TCU is the primary serial port on Tegra194 devices.
>
> Add a TCU driver utilizing the mailbox framework, as the used mailboxes
> are part of Tegra HSP blocks that are already controlled by the Tegra
> HSP mailbox driver.
>
> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
>
> Notes:
> v2:
> - Removed (void) casts for unused variables.
> - Changed the uart_set_options() call to be on one line, even if its
> over 80 characters.
> - Added defines for magic numbers.
> - Style fixes.
> - Changed Kconfig entry to depend on the Tegra HSP driver instead of
> just the mailbox framework.
>
> drivers/tty/serial/Kconfig | 9 ++
> drivers/tty/serial/Makefile | 1 +
> drivers/tty/serial/tegra-tcu.c | 289 +++++++++++++++++++++++++++++++++++++++
> include/uapi/linux/serial_core.h | 3 +
> 4 files changed, 302 insertions(+)
> create mode 100644 drivers/tty/serial/tegra-tcu.c
>
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index df8bd0c7b97d..5fdd336e8937 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -322,6 +322,15 @@ config SERIAL_TEGRA
> are enabled). This driver uses the APB DMA to achieve higher baudrate
> and better performance.
>
> +config SERIAL_TEGRA_TCU
> + tristate "NVIDIA Tegra Combined UART"
> + depends on ARCH_TEGRA && TEGRA_HSP_MBOX
> + select SERIAL_CORE
> + help
> + Support for the mailbox-based TCU (Tegra Combined UART) serial port.
> + TCU is a virtual serial port that allows multiplexing multiple data
> + streams into a single hardware serial port.
> +
> config SERIAL_MAX3100
> tristate "MAX3100 support"
> depends on SPI
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index daac675612df..4ad82231ff8a 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -76,6 +76,7 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
> obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
> obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
> obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
> +obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
> obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
> obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
> obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
> diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
> new file mode 100644
> index 000000000000..b54ebe2ad917
> --- /dev/null
> +++ b/drivers/tty/serial/tegra-tcu.c
> @@ -0,0 +1,289 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
> + */
> +
> +#include <linux/console.h>
> +#include <linux/mailbox_client.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/serial.h>
> +#include <linux/serial_core.h>
> +#include <linux/slab.h>
> +#include <linux/tty.h>
> +#include <linux/tty_flip.h>
> +
> +#define TCU_MBOX_BYTE(i, x) ((x) << (i*8))
> +#define TCU_MBOX_BYTE_V(x, i) (((x) >> (i*8)) & 0xff)
> +#define TCU_MBOX_NUM_BYTES(x) ((x) << 24)
> +#define TCU_MBOX_NUM_BYTES_V(x) (((x) >> 24) & 0x3)
> +#define TCU_MBOX_FLUSH BIT(26)
> +
> +static struct uart_driver tegra_tcu_uart_driver;
> +static struct uart_port tegra_tcu_uart_port;
> +
> +struct tegra_tcu {
> + struct mbox_client tx_client, rx_client;
> + struct mbox_chan *tx, *rx;
> +};
> +
> +static unsigned int tegra_tcu_uart_tx_empty(struct uart_port *port)
> +{
> + return TIOCSER_TEMT;
> +}
> +
> +static void tegra_tcu_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
> +{
> +}
> +
> +static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port *port)
> +{
> + return 0;
> +}
> +
> +static void tegra_tcu_uart_stop_tx(struct uart_port *port)
> +{
> +}
> +
> +static void tegra_tcu_write(const char *s, unsigned int count)
> +{
> + struct tegra_tcu *tcu = tegra_tcu_uart_port.private_data;
> + unsigned int written = 0, i = 0;
> + bool insert_nl = false;
> + uint32_t value = 0;
> +
> + while (i < count) {
> + if (insert_nl) {
> + value |= TCU_MBOX_BYTE(written++, '\n');
> + insert_nl = false;
> + i++;
> + } else if (s[i] == '\n') {
> + value |= TCU_MBOX_BYTE(written++, '\r');
> + insert_nl = true;
> + } else {
> + value |= TCU_MBOX_BYTE(written++, s[i++]);
> + }
> +
> + if (written == 3) {
> + value |= TCU_MBOX_NUM_BYTES(3) | TCU_MBOX_FLUSH;
> + mbox_send_message(tcu->tx, &value);
> + value = 0;
> + written = 0;
> + }
> + }
> +
> + if (written) {
> + value |= TCU_MBOX_NUM_BYTES(written) | TCU_MBOX_FLUSH;
> + mbox_send_message(tcu->tx, &value);
> + }
> +}
> +
> +static void tegra_tcu_uart_start_tx(struct uart_port *port)
> +{
> + struct circ_buf *xmit = &port->state->xmit;
> + unsigned long count;
> +
> + for (;;) {
> + count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
> + if (!count)
> + break;
> +
> + tegra_tcu_write(&xmit->buf[xmit->tail], count);
> + xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
> + }
> +
> + uart_write_wakeup(port);
> +}
> +
> +static void tegra_tcu_uart_stop_rx(struct uart_port *port)
> +{
> +}
> +
> +static void tegra_tcu_uart_break_ctl(struct uart_port *port, int ctl)
> +{
> +}
> +
> +static int tegra_tcu_uart_startup(struct uart_port *port)
> +{
> + return 0;
> +}
> +
> +static void tegra_tcu_uart_shutdown(struct uart_port *port)
> +{
> +}
> +
> +static void tegra_tcu_uart_set_termios(struct uart_port *port,
> + struct ktermios *new,
> + struct ktermios *old)
> +{
> +}
> +
> +static const struct uart_ops tegra_tcu_uart_ops = {
> + .tx_empty = tegra_tcu_uart_tx_empty,
> + .set_mctrl = tegra_tcu_uart_set_mctrl,
> + .get_mctrl = tegra_tcu_uart_get_mctrl,
> + .stop_tx = tegra_tcu_uart_stop_tx,
> + .start_tx = tegra_tcu_uart_start_tx,
> + .stop_rx = tegra_tcu_uart_stop_rx,
> + .break_ctl = tegra_tcu_uart_break_ctl,
> + .startup = tegra_tcu_uart_startup,
> + .shutdown = tegra_tcu_uart_shutdown,
> + .set_termios = tegra_tcu_uart_set_termios,
> +};
> +
> +static void tegra_tcu_console_write(struct console *cons, const char *s,
> + unsigned int count)
> +{
> + tegra_tcu_write(s, count);
> +}
> +
> +static int tegra_tcu_console_setup(struct console *cons, char *options)
> +{
> + if (!tegra_tcu_uart_port.private_data)
> + return -ENODEV;
> +
> + return uart_set_options(&tegra_tcu_uart_port, cons, 115200, 'n', 8, 'n');
> +}
I am curious if we actually need to call uart_set_options() here? Given that
set_termios does nothing, is this actually needed?
> +
> +static struct console tegra_tcu_console = {
> + .name = "ttyTCU",
> + .device = uart_console_device,
> + .flags = CON_PRINTBUFFER | CON_ANYTIME,
> + .index = -1,
> + .write = tegra_tcu_console_write,
> + .setup = tegra_tcu_console_setup,
> + .data = &tegra_tcu_uart_driver,
> +};
> +
> +static struct uart_driver tegra_tcu_uart_driver = {
> + .owner = THIS_MODULE,
> + .driver_name = "tegra-tcu",
> + .dev_name = "ttyTCU",
> + .cons = &tegra_tcu_console,
> + .nr = 1,
> +};
> +
> +static void tegra_tcu_receive(struct mbox_client *client, void *msg_p)
> +{
> + struct tty_port *port = &tegra_tcu_uart_port.state->port;
> + uint32_t msg = *(uint32_t *)msg_p;
> + unsigned int num_bytes;
> + int i;
> +
> + num_bytes = TCU_MBOX_NUM_BYTES_V(msg);
> + for (i = 0; i < num_bytes; i++)
> + tty_insert_flip_char(port, TCU_MBOX_BYTE_V(msg, i), TTY_NORMAL);
> +
> + tty_flip_buffer_push(port);
> +}
> +
> +static int tegra_tcu_probe(struct platform_device *pdev)
> +{
> + struct uart_port *port = &tegra_tcu_uart_port;
> + struct tegra_tcu *tcu;
> + int err;
> +
> + tcu = devm_kzalloc(&pdev->dev, sizeof(*tcu), GFP_KERNEL);
> + if (!tcu)
> + return -ENOMEM;
> +
> + tcu->tx_client.dev = &pdev->dev;
> + tcu->rx_client.dev = &pdev->dev;
> + tcu->rx_client.rx_callback = tegra_tcu_receive;
> +
> + tcu->tx = mbox_request_channel_byname(&tcu->tx_client, "tx");
> + if (IS_ERR(tcu->tx)) {
> + err = PTR_ERR(tcu->tx);
> + dev_err(&pdev->dev, "failed to get tx mailbox: %d\n", err);
> + return err;
> + }
> +
> + tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx");
> + if (IS_ERR(tcu->rx)) {
> + err = PTR_ERR(tcu->rx);
> + dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err);
> + goto free_tx;
> + }
> +
> + err = uart_register_driver(&tegra_tcu_uart_driver);
> + if (err) {
> + dev_err(&pdev->dev, "failed to register UART driver: %d\n",
> + err);
> + goto free_rx;
> + }
> +
> + spin_lock_init(&port->lock);
> + port->dev = &pdev->dev;
> + port->type = PORT_TEGRA_TCU;
> + port->ops = &tegra_tcu_uart_ops;
> + port->fifosize = 1;
> + port->iotype = UPIO_MEM;
> + port->flags = UPF_BOOT_AUTOCONF;
> + port->private_data = tcu;
> +
> + err = uart_add_one_port(&tegra_tcu_uart_driver, port);
> + if (err) {
> + dev_err(&pdev->dev, "failed to add UART port: %d\n", err);
> + goto unregister_uart;
> + }
> +
> + return 0;
> +
> +unregister_uart:
> + uart_unregister_driver(&tegra_tcu_uart_driver);
> +free_rx:
> + mbox_free_channel(tcu->rx);
> +free_tx:
> + mbox_free_channel(tcu->tx);
> +
> + return err;
> +}
> +
> +static int tegra_tcu_remove(struct platform_device *pdev)
> +{
> + uart_remove_one_port(&tegra_tcu_uart_driver, &tegra_tcu_uart_port);
> + uart_unregister_driver(&tegra_tcu_uart_driver);
mbox_free_channel()?
> +
> + return 0;
> +}
> +
> +static const struct of_device_id tegra_tcu_match[] = {
> + { .compatible = "nvidia,tegra194-tcu" },
> + { }
> +};
> +
> +static struct platform_driver tegra_tcu_driver = {
> + .driver = {
> + .name = "tegra-tcu",
> + .of_match_table = tegra_tcu_match,
> + },
> + .probe = tegra_tcu_probe,
> + .remove = tegra_tcu_remove,
> +};
> +
> +static int __init tegra_tcu_init(void)
> +{
> + int err;
> +
> + err = platform_driver_register(&tegra_tcu_driver);
> + if (err)
> + return err;
> +
> + register_console(&tegra_tcu_console);
> +
> + return 0;
> +}
> +module_init(tegra_tcu_init);
> +
> +static void __exit tegra_tcu_exit(void)
> +{
> + unregister_console(&tegra_tcu_console);
> + platform_driver_unregister(&tegra_tcu_driver);
> +}
> +module_exit(tegra_tcu_exit);
> +
> +MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("NVIDIA Tegra Combined UART driver");
> diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
> index dce5f9dae121..69883c32cb98 100644
> --- a/include/uapi/linux/serial_core.h
> +++ b/include/uapi/linux/serial_core.h
> @@ -79,6 +79,9 @@
> /* Nuvoton UART */
> #define PORT_NPCM 40
>
> +/* NVIDIA Tegra Combined UART */
> +#define PORT_TEGRA_TCU 41
> +
> /* Intel EG20 */
> #define PORT_PCH_8LINE 44
> #define PORT_PCH_2LINE 45
>
Otherwise looks good to me.
Cheers
Jon
--
nvpublic
^ permalink raw reply
* KVM guest sometimes failed to boot because of kernel stack overflow if KPTI is enabled on a hisilicon ARM64 platform.
From: Wei Xu @ 2018-06-21 9:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e701eaa8-dcb9-777c-2211-67ee27b43acb@arm.com>
Hi James,
On 2018/6/21 9:38, James Morse wrote:
> Hi Will, Wei,
>
> On 20/06/18 17:25, Wei Xu wrote:
>> On 2018/6/20 23:54, James Morse wrote:
>> I have disabled CONFIG_ARM64_RAS_EXTN and reverted that commit.
>> But I still got the stack overflow issue sometimes.
>> Do you have more hint?
>
>> The log is as below:
>> [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x480fd010]
>> [ 0.000000] Linux version 4.17.0-45865-g2b31fe7-dirty
>
> Could you reproduce this with v4.17? This says there are ~45,000 extra patches,
> and un-committed changes. None of the hashes so far have been commits in
> mainline, so we have no idea what this tree is.
>
I have tried v4.17 and log is as below and also it can be found in the first mail
of this thread.
[ 0.000000] Linux version 4.17.0-45864-g29dcea8-dirty
(joyx at Turing-Arch-b) (gcc version 4.9.1 20140505 (prerelease) (crosstool-NG
linaro-1.13.1-4.9-2014.05 - Linaro GCC 4.9-2014.05)) #6 SMP PREEMPT Fri Jun
15 21:39:52 CST 2018
I will try v4.17.2 and v4.18-rc1.
>
>> (joyx at Turing-Arch-b) (gcc version 4.9.1 20140505 (prerelease) (crosstool-NG
>> linaro-1.13.1-4.9-2014.05 - Linaro GCC 4.9-2014.05)) #10 SMP PREEMPT Wed Jun 20
>> 23:59:05 CST 2018
>
>> [ 0.000000] CPU0: using LPI pending table @0x000000007d860000
>> [ 0.000000] GIC: PPI11 is secure or misconfigured
>> [ 0.000000] arch_timer: WARNING: Invalid trigger for IRQ3, assuming level
>> low
>> [ 0.000000] arch_timer: WARNING: Please fix your firmware
>> [ 0.000000] arch_timer: cp15 timer(s) running at 100.00MHz (virt).
>
> (No idea what these mean, but I doubt they are relevant)
>
I will try with mainline qemu 2.12.0.
Thanks!
Best Regards,
Wei
>
>> [ 0.042421] Insufficient stack space to handle exception!
>> [ 0.042423] ESR: 0x96000046 -- DABT (current EL)
>> [ 0.043730] FAR: 0xffff0000093a80e0
>> [ 0.044714] Task stack: [0xffff0000093a8000..0xffff0000093ac000]
>
> This was a level 2 translation fault on a write, to an address that is within
> the stack....
>
>
>> [ 0.051113] IRQ stack: [0xffff000008000000..0xffff000008004000]
>> [ 0.057610] Overflow stack: [0xffff80003efce2f0..0xffff80003efcf2f0]
>> [ 0.064003] CPU: 0 PID: 12 Comm: migration/0 Not tainted
>> 4.17.0-45865-g2b31fe7-dirty #10
>> [ 0.072201] Hardware name: linux,dummy-virt (DT)
>
>> [ 0.076797] pstate: 604003c5 (nZCv DAIF +PAN -UAO)
>> [ 0.081727] pc : el1_sync+0x0/0xb0
>
> ... from the vectors.
>
>
>> [ 0.085217] lr : kpti_install_ng_mappings+0x120/0x214
>
> What I think is happening is: we come out of the kpti idmap with the stack
> unmapped. Shortly after we access the stack, which faults. el1_sync faults as
> well when it tries to push the registers to the stack, and we keep going until
> we overflow the stack.
>
> I can't reproduce this with kvmtool or qemu in the model.
>
>
> Thanks,
>
> James
>
> .
>
^ permalink raw reply
* [PATCH RESEND 1/2] ti: wkup_m3_ipc: Add rtc_only with ddr in self refresh mode support
From: Keerthy @ 2018-06-21 9:22 UTC (permalink / raw)
To: linux-arm-kernel
Adds rtc_only support. This needs resume function to shutdown and
reboot the m3.
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
This is tested on am437x-gp-evm and target for 4.19
drivers/soc/ti/wkup_m3_ipc.c | 41 +++++++++++++++++++++++++++++++++++++++++
include/linux/wkup_m3_ipc.h | 3 +++
2 files changed, 44 insertions(+)
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index 369aef5..b732c39 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -329,12 +329,24 @@ static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
return 0;
}
+/**
+ * wkup_m3_set_rtc_only - Set the rtc_only flag
+ * @wkup_m3_wakeup: struct wkup_m3_wakeup_src * gets assigned the
+ * wakeup src value
+ */
+static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
+{
+ if (m3_ipc_state)
+ m3_ipc_state->is_rtc_only = true;
+}
+
static struct wkup_m3_ipc_ops ipc_ops = {
.set_mem_type = wkup_m3_set_mem_type,
.set_resume_address = wkup_m3_set_resume_address,
.prepare_low_power = wkup_m3_prepare_low_power,
.finish_low_power = wkup_m3_finish_low_power,
.request_pm_status = wkup_m3_request_pm_status,
+ .set_rtc_only = wkup_m3_set_rtc_only,
};
/**
@@ -484,6 +496,32 @@ static int wkup_m3_ipc_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int wkup_m3_ipc_suspend(struct device *dev)
+{
+ /*
+ * Nothing needs to be done on suspend even with rtc_only flag set
+ */
+ return 0;
+}
+
+static int wkup_m3_ipc_resume(struct device *dev)
+{
+ if (m3_ipc_state->is_rtc_only) {
+ rproc_shutdown(m3_ipc_state->rproc);
+ rproc_boot(m3_ipc_state->rproc);
+ }
+
+ m3_ipc_state->is_rtc_only = false;
+
+ return 0;
+}
+
+static const struct dev_pm_ops wkup_m3_ipc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(wkup_m3_ipc_suspend, wkup_m3_ipc_resume)
+};
+#endif
+
static const struct of_device_id wkup_m3_ipc_of_match[] = {
{ .compatible = "ti,am3352-wkup-m3-ipc", },
{ .compatible = "ti,am4372-wkup-m3-ipc", },
@@ -497,6 +535,9 @@ static int wkup_m3_ipc_remove(struct platform_device *pdev)
.driver = {
.name = "wkup_m3_ipc",
.of_match_table = wkup_m3_ipc_of_match,
+#ifdef CONFIG_PM
+ .pm = &wkup_m3_ipc_pm_ops,
+#endif
},
};
diff --git a/include/linux/wkup_m3_ipc.h b/include/linux/wkup_m3_ipc.h
index d6ba7d3..d639df1 100644
--- a/include/linux/wkup_m3_ipc.h
+++ b/include/linux/wkup_m3_ipc.h
@@ -40,6 +40,7 @@ struct wkup_m3_ipc {
struct mbox_chan *mbox;
struct wkup_m3_ipc_ops *ops;
+ int is_rtc_only;
};
struct wkup_m3_ipc_ops {
@@ -48,8 +49,10 @@ struct wkup_m3_ipc_ops {
int (*prepare_low_power)(struct wkup_m3_ipc *m3_ipc, int state);
int (*finish_low_power)(struct wkup_m3_ipc *m3_ipc);
int (*request_pm_status)(struct wkup_m3_ipc *m3_ipc);
+ void (*set_rtc_only)(struct wkup_m3_ipc *m3_ipc);
};
struct wkup_m3_ipc *wkup_m3_ipc_get(void);
void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc);
+void wkup_m3_set_rtc_only_mode(void);
#endif /* _LINUX_WKUP_M3_IPC_H */
--
1.9.1
^ permalink raw reply related
* [PATCH RESEND 2/2] soc: ti: wkup_m3_ipc: Add wkup_m3_request_wake_src
From: Keerthy @ 2018-06-21 9:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529572954-22244-1-git-send-email-j-keerthy@ti.com>
From: Dave Gerlach <d-gerlach@ti.com>
Add wkup_m3_request_wake_src to allow users to get the name of
the wakeup source after a DeepSleep or Standby transition.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
This is tested on am437x-gp-evm and target for 4.19
drivers/soc/ti/wkup_m3_ipc.c | 39 +++++++++++++++++++++++++++++++++++++++
include/linux/wkup_m3_ipc.h | 6 ++++++
2 files changed, 45 insertions(+)
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index b732c39..6840688 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -46,6 +46,7 @@
#define M3_BASELINE_VERSION 0x191
#define M3_STATUS_RESP_MASK (0xffff << 16)
#define M3_FW_VERSION_MASK 0xffff
+#define M3_WAKE_SRC_MASK 0xff
#define M3_STATE_UNKNOWN 0
#define M3_STATE_RESET 1
@@ -55,6 +56,23 @@
static struct wkup_m3_ipc *m3_ipc_state;
+static const struct wkup_m3_wakeup_src wakeups[] = {
+ {.irq_nr = 35, .src = "USB0_PHY"},
+ {.irq_nr = 36, .src = "USB1_PHY"},
+ {.irq_nr = 40, .src = "I2C0"},
+ {.irq_nr = 41, .src = "RTC Timer"},
+ {.irq_nr = 42, .src = "RTC Alarm"},
+ {.irq_nr = 43, .src = "Timer0"},
+ {.irq_nr = 44, .src = "Timer1"},
+ {.irq_nr = 45, .src = "UART"},
+ {.irq_nr = 46, .src = "GPIO0"},
+ {.irq_nr = 48, .src = "MPU_WAKE"},
+ {.irq_nr = 49, .src = "WDT0"},
+ {.irq_nr = 50, .src = "WDT1"},
+ {.irq_nr = 51, .src = "ADC_TSC"},
+ {.irq_nr = 0, .src = "Unknown"},
+};
+
static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
{
writel(AM33XX_M3_TXEV_ACK,
@@ -330,6 +348,26 @@ static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
}
/**
+ * wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3
+ * @m3_ipc: Pointer to wkup_m3_ipc context
+ */
+static const char *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
+{
+ unsigned int wakeup_src_idx;
+ int j, val;
+
+ val = wkup_m3_ctrl_ipc_read(m3_ipc, 6);
+
+ wakeup_src_idx = val & M3_WAKE_SRC_MASK;
+
+ for (j = 0; j < ARRAY_SIZE(wakeups) - 1; j++) {
+ if (wakeups[j].irq_nr == wakeup_src_idx)
+ return wakeups[j].src;
+ }
+ return wakeups[j].src;
+}
+
+/**
* wkup_m3_set_rtc_only - Set the rtc_only flag
* @wkup_m3_wakeup: struct wkup_m3_wakeup_src * gets assigned the
* wakeup src value
@@ -346,6 +384,7 @@ static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
.prepare_low_power = wkup_m3_prepare_low_power,
.finish_low_power = wkup_m3_finish_low_power,
.request_pm_status = wkup_m3_request_pm_status,
+ .request_wake_src = wkup_m3_request_wake_src,
.set_rtc_only = wkup_m3_set_rtc_only,
};
diff --git a/include/linux/wkup_m3_ipc.h b/include/linux/wkup_m3_ipc.h
index d639df1..e497e62 100644
--- a/include/linux/wkup_m3_ipc.h
+++ b/include/linux/wkup_m3_ipc.h
@@ -43,12 +43,18 @@ struct wkup_m3_ipc {
int is_rtc_only;
};
+struct wkup_m3_wakeup_src {
+ int irq_nr;
+ char src[10];
+};
+
struct wkup_m3_ipc_ops {
void (*set_mem_type)(struct wkup_m3_ipc *m3_ipc, int mem_type);
void (*set_resume_address)(struct wkup_m3_ipc *m3_ipc, void *addr);
int (*prepare_low_power)(struct wkup_m3_ipc *m3_ipc, int state);
int (*finish_low_power)(struct wkup_m3_ipc *m3_ipc);
int (*request_pm_status)(struct wkup_m3_ipc *m3_ipc);
+ const char *(*request_wake_src)(struct wkup_m3_ipc *m3_ipc);
void (*set_rtc_only)(struct wkup_m3_ipc *m3_ipc);
};
--
1.9.1
^ permalink raw reply related
* [PATCH 1/1] arm64/mm: move {idmap_pg_dir, tramp_pg_dir, swapper_pg_dir} to .rodata section
From: Ard Biesheuvel @ 2018-06-21 9:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <70ebe6d7-0745-5606-ae89-8a7b2fb62008@arm.com>
On 21 June 2018 at 10:59, James Morse <james.morse@arm.com> wrote:
> Hi guys,
>
> On 21/06/18 07:39, Ard Biesheuvel wrote:
>> On 21 June 2018 at 04:51, Jun Yao <yaojun8558363@gmail.com> wrote:
>>> On Wed, Jun 20, 2018 at 12:09:49PM +0200, Ard Biesheuvel wrote:
>>>> On 20 June 2018 at 10:57, Jun Yao <yaojun8558363@gmail.com> wrote:
>>>>> Move {idmap_pg_dir,tramp_pg_dir,swapper_pg_dir} to .rodata
>>>>> section. And update the swapper_pg_dir by fixmap.
>>>>>
>>>>
>>>> I think we may be able to get away with not mapping idmap_pg_dir and
>>>> tramp_pg_dir at all.
>>>
>>> I think we need to move tramp_pg_dir to .rodata. The attacker can write
>>> a block-mapping(AP=01) to tramp_pg_dir and then he can access kernel
>>> memory.
>
>> Why does it need to be mapped at all? When do we ever access it from the code?
>
> (We would want to make its fixmap entry read-only too)
>
It already is.
>
>>>> As for swapper_pg_dir, it would indeed be nice if we could keep those
>>>> mappings read-only most of the time, but I'm not sure how useful this
>>>> is if we apply it to the root level only.
>>>
>>> The purpose of it is to make 'KSMA' harder, where an single arbitrary
>>> write is used to add a block mapping to the page-tables, giving the
>>> attacker full access to kernel memory. That's why we just apply it to
>>> the root level only. If the attacker can arbitrary write multiple times,
>>> I think it's hard to defend.
>>>
>>
>> So the assumption is that the root level is more easy to find?
>> Otherwise, I'm not sure I understand why being able to write a level 0
>> entry is so harmful, given that we don't have block mappings at that
>> level.
>
> I think this thing assumes 3-level page tables with 39bit VA.
>
The attack, you mean? Because this code is unlikely to build with that
configuration, given that __pgd_populate() BUILD_BUG()s in that case.
>
>>>>> @@ -417,12 +421,22 @@ static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start,
>>>>>
>>>>> void __init mark_linear_text_alias_ro(void)
>>>>> {
>
>>>>> + size = (unsigned long)__init_begin - (unsigned long)swapper_pg_end;
>>>>> + update_mapping_prot(__pa_symbol(swapper_pg_end),
>>>>> + (unsigned long)lm_alias(swapper_pg_end),
>>>>> + size, PAGE_KERNEL_RO);
>>>>
>>>> I don't think this is necessary. Even if some pages are freed, it
>>>> doesn't harm to keep a read-only alias of them here since the new
>>>> owner won't access them via this mapping anyway. So we can keep
>>>> .rodata as a single region.
>>>
>>> To be honest, I didn't think of this issue at first. I later found a
>>> problem when testing the code on qemu:
>>
>> OK, you're right. I missed the fact that this operates on the linear
>> alias, not the kernel mapping itself.
>>
>> What I don't like is that we lose the ability to use block mappings
>> for the entire .rodata section this way. Isn't it possible to move
>> these pgdirs to the end of the .rodata segment, perhaps by using a
>> separate input section name and placing that explicitly? We could even
>> simply forget about freeing those pages, given that [on 4k pages] the
>> benefit of freeing 12 KB of space is likely to get lost in the
>> rounding noise anyway [segments are rounded up to 64 KB in size]
>
> I assumed that to move swapper_pg_dir into the .rodata section we would need to
> break it up. Today its ~3 levels, which we setup in head.S, then do a dance in
> paging_init() so that swapper_pg_dir is always the top level.
>
> We could generate all leves of the 'init_pg_dir' in the __initdata section, then
> copy only the top level into swapper_pg_dir into the rodata section during
> paging_init().
>
Is that complexity truly justified for a security sensitive piece of
code? Can't we just drop the memblock_free() and be done with it?
^ permalink raw reply
* [PATCH 4/9] media: cedrus: make engine type more generic
From: Paul Kocialkowski @ 2018-06-21 9:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180613140714.1686-5-maxime.ripard@bootlin.com>
Hi,
On Wed, 2018-06-13 at 16:07 +0200, Maxime Ripard wrote:
> The sunxi_cedrus_engine enum actually enumerates pretty much the codecs to
> use (or we can easily infer the codec engine from the codec).
>
> Since we will need the codec type as well in some later refactoring, make
> that structure more useful by just enumerating the codec, and converting
> the existing users.
With the comment below taken in account, this is:
Acked-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
> drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h | 6 ++++++
> drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c | 6 +++---
> drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h | 6 +-----
> drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c | 2 +-
> 4 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> index b1ed1c8cb130..a5f83c452006 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> @@ -61,6 +61,12 @@ struct sunxi_cedrus_run {
> };
> };
>
> +enum sunxi_cedrus_codec {
Feel free to rename to cedrus_codec when rebasing on top of the latest
patchset introducing the driver.
Cheers,
Paul
> + SUNXI_CEDRUS_CODEC_MPEG2,
> +
> + SUNXI_CEDRUS_CODEC_LAST,
> +};
> +
> struct sunxi_cedrus_ctx {
> struct v4l2_fh fh;
> struct sunxi_cedrus_dev *dev;
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> index fc688a5c1ea3..bb46a01214e0 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> @@ -41,7 +41,7 @@
> #define SYSCON_SRAM_C1_MAP_VE 0x7fffffff
>
> int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
> - enum sunxi_cedrus_engine engine)
> + enum sunxi_cedrus_codec codec)
> {
> u32 reg = 0;
>
> @@ -53,8 +53,8 @@ int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
>
> reg |= VE_CTRL_CACHE_BUS_BW_128;
>
> - switch (engine) {
> - case SUNXI_CEDRUS_ENGINE_MPEG:
> + switch (codec) {
> + case SUNXI_CEDRUS_CODEC_MPEG2:
> reg |= VE_CTRL_DEC_MODE_MPEG;
> break;
>
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> index 34f3fae462a8..3236c80bfcf4 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> @@ -23,12 +23,8 @@
> #ifndef _SUNXI_CEDRUS_HW_H_
> #define _SUNXI_CEDRUS_HW_H_
>
> -enum sunxi_cedrus_engine {
> - SUNXI_CEDRUS_ENGINE_MPEG,
> -};
> -
> int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
> - enum sunxi_cedrus_engine engine);
> + enum sunxi_cedrus_codec codec);
> void sunxi_cedrus_engine_disable(struct sunxi_cedrus_dev *dev);
>
> int sunxi_cedrus_hw_probe(struct sunxi_cedrus_dev *dev);
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> index 5be3e3b9ceef..85e6fc2fbdb2 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> @@ -83,7 +83,7 @@ void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> }
>
> /* Activate MPEG engine. */
> - sunxi_cedrus_engine_enable(dev, SUNXI_CEDRUS_ENGINE_MPEG);
> + sunxi_cedrus_engine_enable(dev, SUNXI_CEDRUS_CODEC_MPEG2);
>
> /* Set quantization matrices. */
> for (i = 0; i < 64; i++) {
--
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180621/8ee3cf01/attachment-0001.sig>
^ permalink raw reply
* [PATCH 3/6] coresight: Introduce support for Coresight Address Translation Unit
From: Suzuki K Poulose @ 2018-06-21 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620214157.GA20697@xps15>
Hi Mathieu,
On 20/06/1822:41, Mathieu Poirier wrote:
> Hi Suzuki,
>
> On Mon, Jun 18, 2018 at 11:56:16AM +0100, Suzuki K Poulose wrote:
>> Add the initial support for Coresight Address Translation Unit, which
>> augments the TMC in Coresight SoC-600 by providing an improved Scatter
>> Gather mechanism. CATU is always connected to a single TMC-ETR and
>> converts the AXI address with a translated address (from a given SG
>> table with specific format). The CATU should be programmed in pass
>> through mode and enabled if the ETR doesn't translation by CATU.
>
> To me this sentence look broken.
>
Yes, it is broken. It should have been :
"The CATU should be programmed in pass through mode and enabled
even if the ETR doesn't use the translation by CATU."
>> +static int catu_disable_hw(struct catu_drvdata *drvdata)
>> +{
>> + int rc = 0;
>> +
>> + if (catu_wait_for_ready(drvdata)) {
>> + dev_info(drvdata->dev, "Timeout while waiting for READY\n");
>> + rc = -EAGAIN;
>> + }
>> +
>> + catu_write_control(drvdata, 0);
>
> Is waiting for the ready bit before switching the component off comes from
> experimentation with the HW (i.e FPGA)? From what the reference manual
> indicate, CONTROL.ENABLE should be set to 0 first, and then wait for
> STATUS.READY.
You're right. It should be in the reverse order. I will fix it in the next version.
Thanks
Suzuki
^ permalink raw reply
* [PATCH v2 7/8] arm64: tegra: Add nodes for tcu on Tegra194
From: Jon Hunter @ 2018-06-21 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620122042.10950-8-mperttunen@nvidia.com>
On 20/06/18 13:20, Mikko Perttunen wrote:
> Add nodes required for communication through the Tegra Combined UART.
> This includes the AON HSP instance, addition of shared interrupts
> for the TOP0 HSP instance, and finally the TCU node itself. Also
> mark the HSP instances as compatible to tegra194-hsp, as the hardware
> is not identical but is compatible to tegra186-hsp.
>
> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
> arch/arm64/boot/dts/nvidia/tegra194.dtsi | 34 +++++++++++++++++++++++++++++---
> 1 file changed, 31 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> index 6d699815a84f..d7f780b06fe2 100644
> --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
> @@ -217,10 +217,31 @@
> };
>
> hsp_top0: hsp at 3c00000 {
> - compatible = "nvidia,tegra186-hsp";
> + compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp";
> reg = <0x03c00000 0xa0000>;
> - interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
> - interrupt-names = "doorbell";
> + interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "doorbell", "shared0", "shared1", "shared2",
> + "shared3", "shared4", "shared5", "shared6",
> + "shared7";
> + #mbox-cells = <2>;
> + };
> +
> + hsp_aon: hsp at c150000 {
> + compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp";
> + reg = <0x0c150000 0xa0000>;
> + interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "shared0", "shared1", "shared2", "shared3";
> #mbox-cells = <2>;
> };
>
> @@ -382,6 +403,13 @@
> };
> };
>
> + tcu: tcu {
> + compatible = "nvidia,tegra194-tcu";
> + mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_SM 0>,
> + <&hsp_aon TEGRA_HSP_MBOX_TYPE_SM 1>;
> + mbox-names = "rx", "tx";
> + };
> +
> timer {
> compatible = "arm,armv8-timer";
> interrupts = <GIC_PPI 13
>
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Cheers
Jon
--
nvpublic
^ permalink raw reply
* [PATCH 6/9] media: cedrus: Add ops structure
From: Paul Kocialkowski @ 2018-06-21 9:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180613140714.1686-7-maxime.ripard@bootlin.com>
Hi,
On Wed, 2018-06-13 at 16:07 +0200, Maxime Ripard wrote:
> In order to increase the number of codecs supported, we need to decouple
> the MPEG2 only code that was there up until now and turn it into something
> a bit more generic.
>
> Do that by introducing an intermediate ops structure that would need to be
> filled by each supported codec. Start by implementing in that structure the
> setup and trigger hooks that are currently the only functions being
> implemented by codecs support.
>
> To do so, we need to store the current codec in use, which we do at
> start_streaming time.
With the comments below taken in account, this is:
Acked-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
> .../platform/sunxi/cedrus/sunxi_cedrus.c | 2 ++
> .../sunxi/cedrus/sunxi_cedrus_common.h | 11 +++++++
> .../platform/sunxi/cedrus/sunxi_cedrus_dec.c | 10 +++---
> .../sunxi/cedrus/sunxi_cedrus_mpeg2.c | 11 +++++--
> .../sunxi/cedrus/sunxi_cedrus_mpeg2.h | 33 -------------------
> .../sunxi/cedrus/sunxi_cedrus_video.c | 17 +++++++++-
> 6 files changed, 42 insertions(+), 42 deletions(-)
> delete mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
>
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> index ccd41d9a3e41..bc80480f5dfd 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> @@ -244,6 +244,8 @@ static int sunxi_cedrus_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> + dev->dec_ops[SUNXI_CEDRUS_CODEC_MPEG2] = &sunxi_cedrus_dec_ops_mpeg2;
> +
> ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
> if (ret)
> goto unreg_media;
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> index a5f83c452006..c2e2c92d103b 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> @@ -75,6 +75,7 @@ struct sunxi_cedrus_ctx {
> struct v4l2_pix_format_mplane src_fmt;
> struct sunxi_cedrus_fmt *vpu_dst_fmt;
> struct v4l2_pix_format_mplane dst_fmt;
> + enum sunxi_cedrus_codec current_codec;
Nit: for consistency with the way things are named, "codec_current"
probably makes more sense.
IMO using the natural English order is fine for temporary variables, but
less so for variables used in common parts like structures. This allows
seeing "_" as a logical hierarchical delimiter that automatically makes
us end up with consistent prefixes that can easily be grepped for and
derived.
But that's just my 2 cents, it's really not a big deal, especially in
this case!
> struct v4l2_ctrl_handler hdl;
> struct v4l2_ctrl *ctrls[SUNXI_CEDRUS_CTRL_MAX];
> @@ -107,6 +108,14 @@ struct sunxi_cedrus_buffer *vb2_to_cedrus_buffer(const struct vb2_buffer *p)
> return vb2_v4l2_to_cedrus_buffer(to_vb2_v4l2_buffer(p));
> }
>
> +struct sunxi_cedrus_dec_ops {
> + void (*setup)(struct sunxi_cedrus_ctx *ctx,
> + struct sunxi_cedrus_run *run);
> + void (*trigger)(struct sunxi_cedrus_ctx *ctx);
By the way, are we sure that these functions won't ever fail?
I think this is the case for MPEG2 (there is virtually nothing to check
for errors) but perhaps it's different for H264.
> +};
> +
> +extern struct sunxi_cedrus_dec_ops sunxi_cedrus_dec_ops_mpeg2;
> +
> struct sunxi_cedrus_dev {
> struct v4l2_device v4l2_dev;
> struct video_device vfd;
> @@ -130,6 +139,8 @@ struct sunxi_cedrus_dev {
> struct reset_control *rstc;
>
> struct regmap *syscon;
> +
> + struct sunxi_cedrus_dec_ops *dec_ops[SUNXI_CEDRUS_CODEC_LAST];
> };
>
> static inline void sunxi_cedrus_write(struct sunxi_cedrus_dev *dev,
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> index f274408ab5a7..5e552fa05274 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> @@ -28,7 +28,6 @@
> #include <media/v4l2-mem2mem.h>
>
> #include "sunxi_cedrus_common.h"
> -#include "sunxi_cedrus_mpeg2.h"
> #include "sunxi_cedrus_dec.h"
> #include "sunxi_cedrus_hw.h"
>
> @@ -77,6 +76,7 @@ void sunxi_cedrus_device_work(struct work_struct *work)
> void sunxi_cedrus_device_run(void *priv)
> {
> struct sunxi_cedrus_ctx *ctx = priv;
> + struct sunxi_cedrus_dev *dev = ctx->dev;
> struct sunxi_cedrus_run run = { 0 };
> struct media_request *src_req, *dst_req;
> unsigned long flags;
> @@ -120,8 +120,6 @@ void sunxi_cedrus_device_run(void *priv)
> case V4L2_PIX_FMT_MPEG2_FRAME:
> CHECK_CONTROL(ctx, SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR);
> run.mpeg2.hdr = get_ctrl_ptr(ctx, SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR);
> - sunxi_cedrus_mpeg2_setup(ctx, &run);
> -
> break;
>
> default:
> @@ -129,6 +127,9 @@ void sunxi_cedrus_device_run(void *priv)
> }
> #undef CHECK_CONTROL
>
> + if (!ctx->job_abort)
> + dev->dec_ops[ctx->current_codec]->setup(ctx, &run);
> +
> unlock_complete:
> spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
>
> @@ -143,8 +144,7 @@ void sunxi_cedrus_device_run(void *priv)
> spin_lock_irqsave(&ctx->dev->irq_lock, flags);
>
> if (!ctx->job_abort) {
> - if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_MPEG2_FRAME)
> - sunxi_cedrus_mpeg2_trigger(ctx);
> + dev->dec_ops[ctx->current_codec]->trigger(ctx);
> } else {
> v4l2_m2m_buf_done(run.src, VB2_BUF_STATE_ERROR);
> v4l2_m2m_buf_done(run.dst, VB2_BUF_STATE_ERROR);
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> index d1d7a3cfce0d..e25075bb5779 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> @@ -52,8 +52,8 @@ static const u8 mpeg_default_non_intra_quant[64] = {
>
> #define m_niq(i) ((i << 8) | mpeg_default_non_intra_quant[i])
>
> -void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> - struct sunxi_cedrus_run *run)
> +static void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> + struct sunxi_cedrus_run *run)
> {
> struct sunxi_cedrus_dev *dev = ctx->dev;
> const struct v4l2_ctrl_mpeg2_frame_hdr *frame_hdr = run->mpeg2.hdr;
> @@ -148,9 +148,14 @@ void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> sunxi_cedrus_write(dev, src_buf_addr + VBV_SIZE - 1, VE_MPEG_VLD_END);
> }
>
> -void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx)
> +static void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx)
> {
> struct sunxi_cedrus_dev *dev = ctx->dev;
>
> sunxi_cedrus_write(dev, VE_TRIG_MPEG2, VE_MPEG_TRIGGER);
> }
> +
> +struct sunxi_cedrus_dec_ops sunxi_cedrus_dec_ops_mpeg2 = {
> + .setup = sunxi_cedrus_mpeg2_setup,
> + .trigger = sunxi_cedrus_mpeg2_trigger,
> +};
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
> deleted file mode 100644
> index 4c380becfa1a..000000000000
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
> +++ /dev/null
> @@ -1,33 +0,0 @@
> -/*
> - * Sunxi-Cedrus VPU driver
> - *
> - * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> - * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> - *
> - * Based on the vim2m driver, that is:
> - *
> - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> - * Pawel Osciak, <pawel@osciak.com>
> - * Marek Szyprowski, <m.szyprowski@samsung.com>
> - *
> - * This software is licensed under the terms of the GNU General Public
> - * License version 2, as published by the Free Software Foundation, and
> - * may be copied, distributed, and modified under those terms.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> - */
> -
> -#ifndef _SUNXI_CEDRUS_MPEG2_H_
> -#define _SUNXI_CEDRUS_MPEG2_H_
> -
> -struct sunxi_cedrus_ctx;
> -struct sunxi_cedrus_run;
> -
> -void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> - struct sunxi_cedrus_run *run);
> -void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx);
> -
> -#endif
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> index 089abfe6bfeb..fb7b081a5bb7 100644
> --- a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> @@ -28,7 +28,6 @@
> #include <media/v4l2-mem2mem.h>
>
> #include "sunxi_cedrus_common.h"
> -#include "sunxi_cedrus_mpeg2.h"
> #include "sunxi_cedrus_dec.h"
> #include "sunxi_cedrus_hw.h"
>
> @@ -414,6 +413,21 @@ static int sunxi_cedrus_buf_prepare(struct vb2_buffer *vb)
> return 0;
> }
>
> +static int sunxi_cedrus_start_streaming(struct vb2_queue *q, unsigned int count)
> +{
> + struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(q);
> +
> + switch (ctx->vpu_src_fmt->fourcc) {
> + case V4L2_PIX_FMT_MPEG2_FRAME:
> + ctx->current_codec = SUNXI_CEDRUS_CODEC_MPEG2;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> static void sunxi_cedrus_stop_streaming(struct vb2_queue *q)
> {
> struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(q);
> @@ -462,6 +476,7 @@ static struct vb2_ops sunxi_cedrus_qops = {
> .buf_cleanup = sunxi_cedrus_buf_cleanup,
> .buf_queue = sunxi_cedrus_buf_queue,
> .buf_request_complete = sunxi_cedrus_buf_request_complete,
> + .start_streaming = sunxi_cedrus_start_streaming,
> .stop_streaming = sunxi_cedrus_stop_streaming,
> .wait_prepare = vb2_ops_wait_prepare,
> .wait_finish = vb2_ops_wait_finish,
--
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180621/d52423c9/attachment.sig>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox