* [PATCH] net/tap: add probe finish call for tun secondary
From: Vipin Varghese @ 2018-07-24 5:05 UTC (permalink / raw)
To: dev, ferruh.yigit; +Cc: Vipin Varghese
Invoke rte_eth_dev_probing_finish for rte_pmd_tun_probe.
Signed-off-by: Vipin Varghese <vipin.varghese@intel.com>
---
drivers/net/tap/rte_eth_tap.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index 4493507..8c0c5d6 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1879,6 +1879,7 @@ rte_pmd_tun_probe(struct rte_vdev_device *dev)
return -1;
}
eth_dev->dev_ops = &ops;
+ rte_eth_dev_probing_finish(eth_dev);
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Joel Stanley @ 2018-07-24 4:59 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <1532408201.2611907.1450747808.5F518C30@webmail.messagingengine.com>
On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
>
>
> On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
>> This enables the devices used in the AST2400 family of BMC SoCs:
>>
>> - VUART
>> - SPI NOR
>> - LPC controller
>> - LPC snoop (port 80)
>> - Ethernet
>> - GPIO
>> - ADC
>> - I2C
>> - Random number generator
>> - IPMI KCS
>> - IPMI BT
>> - Fan/Tach
>>
>> Signed-off-by: Joel Stanley <joel@jms.id.au>
>> ---
>> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
>> 1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
>> multi_v5_defconfig
>> index b647e249908e..318b76fa26d1 100644
>> --- a/arch/arm/configs/multi_v5_defconfig
>> +++ b/arch/arm/configs/multi_v5_defconfig
>> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
>> CONFIG_MTD_NAND=y
>> CONFIG_MTD_NAND_ATMEL=y
>> CONFIG_MTD_NAND_ORION=y
>> +CONFIG_MTD_SPI_NOR=y
>> +CONFIG_SPI_ASPEED_SMC=y
>> CONFIG_MTD_UBI=y
>> CONFIG_BLK_DEV_LOOP=y
>> CONFIG_ATMEL_TCLIB=y
>> CONFIG_ATMEL_SSC=m
>> +CONFIG_ASPEED_LPC_CTRL=m
>> +CONFIG_ASPEED_LPC_SNOOP=m
>
> Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
I tried to follow what the existing config did. Some things are
modules, but some subsystems aren't.
I figured there's no harm in getting some build coverage of our
drivers being modules.
Cheers,
Joel
^ permalink raw reply
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Joel Stanley @ 2018-07-24 4:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1532408201.2611907.1450747808.5F518C30@webmail.messagingengine.com>
On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
>
>
> On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
>> This enables the devices used in the AST2400 family of BMC SoCs:
>>
>> - VUART
>> - SPI NOR
>> - LPC controller
>> - LPC snoop (port 80)
>> - Ethernet
>> - GPIO
>> - ADC
>> - I2C
>> - Random number generator
>> - IPMI KCS
>> - IPMI BT
>> - Fan/Tach
>>
>> Signed-off-by: Joel Stanley <joel@jms.id.au>
>> ---
>> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
>> 1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
>> multi_v5_defconfig
>> index b647e249908e..318b76fa26d1 100644
>> --- a/arch/arm/configs/multi_v5_defconfig
>> +++ b/arch/arm/configs/multi_v5_defconfig
>> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
>> CONFIG_MTD_NAND=y
>> CONFIG_MTD_NAND_ATMEL=y
>> CONFIG_MTD_NAND_ORION=y
>> +CONFIG_MTD_SPI_NOR=y
>> +CONFIG_SPI_ASPEED_SMC=y
>> CONFIG_MTD_UBI=y
>> CONFIG_BLK_DEV_LOOP=y
>> CONFIG_ATMEL_TCLIB=y
>> CONFIG_ATMEL_SSC=m
>> +CONFIG_ASPEED_LPC_CTRL=m
>> +CONFIG_ASPEED_LPC_SNOOP=m
>
> Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
I tried to follow what the existing config did. Some things are
modules, but some subsystems aren't.
I figured there's no harm in getting some build coverage of our
drivers being modules.
Cheers,
Joel
^ permalink raw reply
* [ovmf test] 125531: all pass - PUSHED
From: osstest service owner @ 2018-07-24 4:59 UTC (permalink / raw)
To: xen-devel, osstest-admin
flight 125531 ovmf real [real]
http://logs.test-lab.xenproject.org/osstest/logs/125531/
Perfect :-)
All tests in this flight passed as required
version targeted for testing:
ovmf 005c855dc6be0f61f76de0d7ec4a62ee737518d6
baseline version:
ovmf 549ae85ce1b00228c3abcf6a9e4022c4f4fba5ed
Last test of basis 125523 2018-07-23 16:10:55 Z 0 days
Testing same since 125531 2018-07-24 01:10:54 Z 0 days 1 attempts
------------------------------------------------------------
People who touched revisions under test:
Marvin H?user <Marvin.Haeuser@outlook.com>
Marvin Haeuser <Marvin.Haeuser@outlook.com>
jobs:
build-amd64-xsm pass
build-i386-xsm pass
build-amd64 pass
build-i386 pass
build-amd64-libvirt pass
build-i386-libvirt pass
build-amd64-pvops pass
build-i386-pvops pass
test-amd64-amd64-xl-qemuu-ovmf-amd64 pass
test-amd64-i386-xl-qemuu-ovmf-amd64 pass
------------------------------------------------------------
sg-report-flight on osstest.test-lab.xenproject.org
logs: /home/logs/logs
images: /home/logs/images
Logs, config files, etc. are available at
http://logs.test-lab.xenproject.org/osstest/logs
Explanation of these reports, and of osstest in general, is at
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README.email;hb=master
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README;hb=master
Test harness code can be found at
http://xenbits.xen.org/gitweb?p=osstest.git;a=summary
Pushing revision :
To xenbits.xen.org:/home/xen/git/osstest/ovmf.git
549ae85ce1..005c855dc6 005c855dc6be0f61f76de0d7ec4a62ee737518d6 -> xen-tested-master
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Andrew Jeffery @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <CACPK8Xd0ViuVAHgD4Nem5e_th0pf=4hmC=3d0XbLRGGzcDTMDg@mail.gmail.com>
On Tue, 24 Jul 2018, at 14:29, Joel Stanley wrote:
> On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
> >
> >
> > On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> >> This enables the devices used in the AST2400 family of BMC SoCs:
> >>
> >> - VUART
> >> - SPI NOR
> >> - LPC controller
> >> - LPC snoop (port 80)
> >> - Ethernet
> >> - GPIO
> >> - ADC
> >> - I2C
> >> - Random number generator
> >> - IPMI KCS
> >> - IPMI BT
> >> - Fan/Tach
> >>
> >> Signed-off-by: Joel Stanley <joel@jms.id.au>
> >> ---
> >> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
> >> 1 file changed, 13 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> >> multi_v5_defconfig
> >> index b647e249908e..318b76fa26d1 100644
> >> --- a/arch/arm/configs/multi_v5_defconfig
> >> +++ b/arch/arm/configs/multi_v5_defconfig
> >> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
> >> CONFIG_MTD_NAND=y
> >> CONFIG_MTD_NAND_ATMEL=y
> >> CONFIG_MTD_NAND_ORION=y
> >> +CONFIG_MTD_SPI_NOR=y
> >> +CONFIG_SPI_ASPEED_SMC=y
> >> CONFIG_MTD_UBI=y
> >> CONFIG_BLK_DEV_LOOP=y
> >> CONFIG_ATMEL_TCLIB=y
> >> CONFIG_ATMEL_SSC=m
> >> +CONFIG_ASPEED_LPC_CTRL=m
> >> +CONFIG_ASPEED_LPC_SNOOP=m
> >
> > Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
>
> I tried to follow what the existing config did. Some things are
> modules, but some subsystems aren't.
>
> I figured there's no harm in getting some build coverage of our
> drivers being modules.
Righto.
Acked-by: Andrew Jeffery <andrew@aj.id.au>
>
> Cheers,
>
> Joel
^ permalink raw reply
* [PATCH 3/3] ARM: config: multi_v5: Enable ASPEED drivers
From: Andrew Jeffery @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACPK8Xd0ViuVAHgD4Nem5e_th0pf=4hmC=3d0XbLRGGzcDTMDg@mail.gmail.com>
On Tue, 24 Jul 2018, at 14:29, Joel Stanley wrote:
> On 24 July 2018 at 14:26, Andrew Jeffery <andrew@aj.id.au> wrote:
> >
> >
> > On Wed, 18 Jul 2018, at 23:23, Joel Stanley wrote:
> >> This enables the devices used in the AST2400 family of BMC SoCs:
> >>
> >> - VUART
> >> - SPI NOR
> >> - LPC controller
> >> - LPC snoop (port 80)
> >> - Ethernet
> >> - GPIO
> >> - ADC
> >> - I2C
> >> - Random number generator
> >> - IPMI KCS
> >> - IPMI BT
> >> - Fan/Tach
> >>
> >> Signed-off-by: Joel Stanley <joel@jms.id.au>
> >> ---
> >> arch/arm/configs/multi_v5_defconfig | 14 +++++++++++++-
> >> 1 file changed, 13 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/
> >> multi_v5_defconfig
> >> index b647e249908e..318b76fa26d1 100644
> >> --- a/arch/arm/configs/multi_v5_defconfig
> >> +++ b/arch/arm/configs/multi_v5_defconfig
> >> @@ -90,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
> >> CONFIG_MTD_NAND=y
> >> CONFIG_MTD_NAND_ATMEL=y
> >> CONFIG_MTD_NAND_ORION=y
> >> +CONFIG_MTD_SPI_NOR=y
> >> +CONFIG_SPI_ASPEED_SMC=y
> >> CONFIG_MTD_UBI=y
> >> CONFIG_BLK_DEV_LOOP=y
> >> CONFIG_ATMEL_TCLIB=y
> >> CONFIG_ATMEL_SSC=m
> >> +CONFIG_ASPEED_LPC_CTRL=m
> >> +CONFIG_ASPEED_LPC_SNOOP=m
> >
> > Any reason that you switch between module and built-in throughout? It's not clear from the commit message.
>
> I tried to follow what the existing config did. Some things are
> modules, but some subsystems aren't.
>
> I figured there's no harm in getting some build coverage of our
> drivers being modules.
Righto.
Acked-by: Andrew Jeffery <andrew@aj.id.au>
>
> Cheers,
>
> Joel
^ permalink raw reply
* [PATCH 0/5] fsi: Convert misc devs to proper chardevs and more
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
This converts the various FSI devices from misc dev to chardev,
as there can potentially be too much of them for misc devs limited
minors, and because there are some lifetime issues with the current
support.
This provide a common infrastructure to allocate an FSI major and
distribute minors in a way that keeps it compatible with existing
userspace. A new representation grouping FSI devices under a
/dev/fsi directory is optinally provided, which will work in
conjunction with new udev scripts aimed at providing fixed ID
based symlinks.
A side effect of those conversions is to fix some object lifetime
issues caused by a mixup between devm_kzalloc and proper object
lifetime.
This series also adds a /dev{/fsi}/cfamN chardev for raw CFAM
access that will superseed the existing "raw" sysfs file.
Finally there's also a locking fix to avoid horrible mixups if
the "rescan" file is poked while a rescan is already in progress.
^ permalink raw reply
* [PATCH 1/5] fsi: Add new central chardev support
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
The various FSI devices (sbefifo, occ, scom, more to come)
currently use misc devices.
This is problematic as the minor device space for misc is
limited and there can be a lot of them. Also it limits our
ability to move them to a dedicated /dev/fsi directory or
to be smart about device naming and numbering.
It also means we have IDAs on every single of these drivers
This creates a common fsi "device_type" for the optional
/dev/fsi grouping and a dev_t allocator for all FSI devices.
"Legacy" devices get to use a backward compatible numbering
scheme (as long as chip id <16 and there's only one copy
of a given unit type per chip).
A single major number and a single IDA are shared for all
FSI devices.
This doesn't convert the FSI device drivers to use the new
scheme yet, they will be converted individually.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/Kconfig | 15 +++++++
drivers/fsi/fsi-core.c | 95 +++++++++++++++++++++++++++++++++++++++++-
include/linux/fsi.h | 12 +++++-
3 files changed, 119 insertions(+), 3 deletions(-)
diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index 8d82b1e60514..af3a20dd5aa4 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -12,6 +12,21 @@ menuconfig FSI
if FSI
+config FSI_NEW_DEV_NODE
+ bool "Create '/dev/fsi' directory for char devices"
+ default n
+ ---help---
+ This option causes char devices created for FSI devices to be
+ located under a common /dev/fsi/ directory. Set to N unless your
+ userspace has been updated to handle the new location.
+
+ Additionally, it also causes the char device names to be offset
+ by one so that chip 0 will have /dev/scom1 and chip1 /dev/scom2
+ to match old userspace expectations.
+
+ New userspace will use udev rules to generate predictable access
+ symlinks in /dev/fsi/by-path when this option is enabled.
+
config FSI_MASTER_GPIO
tristate "GPIO-based FSI master"
depends on GPIOLIB
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index eab6c5c4990e..faa1760a5a40 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -92,6 +92,13 @@ struct fsi_slave {
static const int slave_retries = 2;
static int discard_errors;
+static dev_t fsi_base_dev;
+static DEFINE_IDA(fsi_minor_ida);
+#define FSI_CHAR_MAX_DEVICES 0x1000
+
+/* Legacy /dev numbering: 4 devices per chip, 16 chips */
+#define FSI_CHAR_LEGACY_TOP 64
+
static int fsi_master_read(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, void *val, size_t size);
static int fsi_master_write(struct fsi_master *master, int link,
@@ -627,6 +634,7 @@ static void fsi_slave_release(struct device *dev)
{
struct fsi_slave *slave = to_fsi_slave(dev);
+ fsi_free_minor(slave->dev.devt);
of_node_put(dev->of_node);
kfree(slave);
}
@@ -729,6 +737,75 @@ static ssize_t chip_id_show(struct device *dev,
static DEVICE_ATTR_RO(chip_id);
+static char *fsi_cdev_devnode(struct device *dev, umode_t *mode,
+ kuid_t *uid, kgid_t *gid)
+{
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return kasprintf(GFP_KERNEL, "fsi/%s", dev_name(dev));
+#else
+ return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
+#endif
+}
+
+const struct device_type fsi_cdev_type = {
+ .name = "fsi-cdev",
+ .devnode = fsi_cdev_devnode,
+};
+EXPORT_SYMBOL_GPL(fsi_cdev_type);
+
+/* Backward compatible /dev/ numbering in "old style" mode */
+static int fsi_adjust_index(int index)
+{
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return index;
+#else
+ return index + 1;
+#endif
+}
+
+static int __fsi_get_new_minor(struct fsi_slave *slave, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index)
+{
+ int cid = slave->chip_id;
+ int id;
+
+ /* Check if we qualify for legacy numbering */
+ if (cid >= 0 && cid < 16 && type < 4) {
+ /* Try reserving the legacy number */
+ id = (cid << 4) | type;
+ id = ida_simple_get(&fsi_minor_ida, id, id + 1, GFP_KERNEL);
+ if (id >= 0) {
+ *out_index = fsi_adjust_index(cid);
+ *out_dev = fsi_base_dev + id;
+ return 0;
+ }
+ /* Other failure */
+ if (id != -ENOSPC)
+ return id;
+ /* Fallback to non-legacy allocation */
+ }
+ id = ida_simple_get(&fsi_minor_ida, FSI_CHAR_LEGACY_TOP,
+ FSI_CHAR_MAX_DEVICES, GFP_KERNEL);
+ if (id < 0)
+ return id;
+ *out_index = fsi_adjust_index(id);
+ *out_dev = fsi_base_dev + id;
+ return 0;
+}
+
+int fsi_get_new_minor(struct fsi_device *fdev, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index)
+{
+ return __fsi_get_new_minor(fdev->slave, type, out_dev, out_index);
+}
+EXPORT_SYMBOL_GPL(fsi_get_new_minor);
+
+void fsi_free_minor(dev_t dev)
+{
+ ida_simple_remove(&fsi_minor_ida, MINOR(dev));
+}
+EXPORT_SYMBOL_GPL(fsi_free_minor);
+
static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
{
uint32_t chip_id;
@@ -953,7 +1030,7 @@ static int fsi_slave_remove_device(struct device *dev, void *arg)
static int fsi_master_remove_slave(struct device *dev, void *arg)
{
device_for_each_child(dev, NULL, fsi_slave_remove_device);
- device_unregister(dev);
+ put_device(dev);
return 0;
}
@@ -1091,13 +1168,27 @@ EXPORT_SYMBOL_GPL(fsi_bus_type);
static int __init fsi_init(void)
{
- return bus_register(&fsi_bus_type);
+ int rc;
+
+ rc = alloc_chrdev_region(&fsi_base_dev, 0, FSI_CHAR_MAX_DEVICES, "fsi");
+ if (rc)
+ return rc;
+ rc = bus_register(&fsi_bus_type);
+ if (rc)
+ goto fail_bus;
+ return 0;
+
+ fail_bus:
+ unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES);
+ return rc;
}
postcore_initcall(fsi_init);
static void fsi_exit(void)
{
bus_unregister(&fsi_bus_type);
+ unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES);
+ ida_destroy(&fsi_minor_ida);
}
module_exit(fsi_exit);
module_param(discard_errors, int, 0664);
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 141fd38d061f..ec3be0d5b786 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -76,8 +76,18 @@ extern int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
extern int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
const void *val, size_t size);
+extern struct bus_type fsi_bus_type;
+extern const struct device_type fsi_cdev_type;
+enum fsi_dev_type {
+ fsi_dev_cfam,
+ fsi_dev_sbefifo,
+ fsi_dev_scom,
+ fsi_dev_occ
+};
-extern struct bus_type fsi_bus_type;
+extern int fsi_get_new_minor(struct fsi_device *fdev, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index);
+extern void fsi_free_minor(dev_t dev);
#endif /* LINUX_FSI_H */
--
2.17.1
^ permalink raw reply related
* [PATCH 2/5] fsi: sbefifo: Convert to use the new chardev
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
This converts FSI sbefifo to use the new fsi-core controlled
chardev allocator and use a real cdev instead of a miscdev.
One side effect is to fix the object lifetime by removing
the use of devm_kzalloc() for something that contains kobjects,
and using proper reference counting.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-sbefifo.c | 84 +++++++++++++++++++++++++--------------
1 file changed, 55 insertions(+), 29 deletions(-)
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 33a5d9a43a07..8a185f53c9d8 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -17,9 +17,8 @@
#include <linux/fs.h>
#include <linux/fsi.h>
#include <linux/fsi-sbefifo.h>
-#include <linux/idr.h>
#include <linux/kernel.h>
-#include <linux/miscdevice.h>
+#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
@@ -118,11 +117,11 @@ struct sbefifo {
uint32_t magic;
#define SBEFIFO_MAGIC 0x53424546 /* "SBEF" */
struct fsi_device *fsi_dev;
- struct miscdevice mdev;
+ struct device dev;
+ struct cdev cdev;
struct mutex lock;
- char name[32];
- int idx;
bool broken;
+ bool dead;
bool async_ffdc;
};
@@ -133,9 +132,9 @@ struct sbefifo_user {
size_t pending_len;
};
-static DEFINE_IDA(sbefifo_ida);
static DEFINE_MUTEX(sbefifo_ffdc_mutex);
+
static void __sbefifo_dump_ffdc(struct device *dev, const __be32 *ffdc,
size_t ffdc_sz, bool internal)
{
@@ -667,6 +666,9 @@ static int __sbefifo_submit(struct sbefifo *sbefifo,
struct device *dev = &sbefifo->fsi_dev->dev;
int rc;
+ if (sbefifo->dead)
+ return -ENODEV;
+
if (cmd_len < 2 || be32_to_cpu(command[0]) != cmd_len) {
dev_vdbg(dev, "Invalid command len %zd (header: %d)\n",
cmd_len, be32_to_cpu(command[0]));
@@ -751,8 +753,7 @@ EXPORT_SYMBOL_GPL(sbefifo_submit);
*/
static int sbefifo_user_open(struct inode *inode, struct file *file)
{
- struct sbefifo *sbefifo = container_of(file->private_data,
- struct sbefifo, mdev);
+ struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev);
struct sbefifo_user *user;
user = kzalloc(sizeof(struct sbefifo_user), GFP_KERNEL);
@@ -889,6 +890,14 @@ static const struct file_operations sbefifo_fops = {
.release = sbefifo_user_release,
};
+static void sbefifo_free(struct device *dev)
+{
+ struct sbefifo *sbefifo = container_of(dev, struct sbefifo, dev);
+
+ put_device(&sbefifo->fsi_dev->dev);
+ kfree(sbefifo);
+}
+
/*
* Probe/remove
*/
@@ -900,15 +909,23 @@ static int sbefifo_probe(struct device *dev)
struct device_node *np;
struct platform_device *child;
char child_name[32];
- int rc, child_idx = 0;
+ int rc, didx, child_idx = 0;
dev_dbg(dev, "Found sbefifo device\n");
- sbefifo = devm_kzalloc(dev, sizeof(*sbefifo), GFP_KERNEL);
+ sbefifo = kzalloc(sizeof(*sbefifo), GFP_KERNEL);
if (!sbefifo)
return -ENOMEM;
+
+ /* Grab a reference to the device (parent of our cdev), we'll drop it later */
+ if (!get_device(dev)) {
+ return -ENODEV;
+ kfree(sbefifo);
+ }
+
sbefifo->magic = SBEFIFO_MAGIC;
sbefifo->fsi_dev = fsi_dev;
+ dev_set_drvdata(dev, sbefifo);
mutex_init(&sbefifo->lock);
/*
@@ -919,28 +936,30 @@ static int sbefifo_probe(struct device *dev)
if (rc && rc != -ESHUTDOWN)
dev_err(dev, "Initial HW cleanup failed, will retry later\n");
- sbefifo->idx = ida_simple_get(&sbefifo_ida, 1, INT_MAX, GFP_KERNEL);
- snprintf(sbefifo->name, sizeof(sbefifo->name), "sbefifo%d",
- sbefifo->idx);
+ /* Create chardev for userspace access */
+ sbefifo->dev.type = &fsi_cdev_type;
+ sbefifo->dev.parent = dev;
+ sbefifo->dev.release = sbefifo_free;
+ device_initialize(&sbefifo->dev);
- dev_set_drvdata(dev, sbefifo);
+ /* Allocate a minor in the FSI space */
+ rc = fsi_get_new_minor(fsi_dev, fsi_dev_sbefifo, &sbefifo->dev.devt, &didx);
+ if (rc)
+ goto err;
- /* Create misc chardev for userspace access */
- sbefifo->mdev.minor = MISC_DYNAMIC_MINOR;
- sbefifo->mdev.fops = &sbefifo_fops;
- sbefifo->mdev.name = sbefifo->name;
- sbefifo->mdev.parent = dev;
- rc = misc_register(&sbefifo->mdev);
+ dev_set_name(&sbefifo->dev, "sbefifo%d", didx);
+ cdev_init(&sbefifo->cdev, &sbefifo_fops);
+ rc = cdev_device_add(&sbefifo->cdev, &sbefifo->dev);
if (rc) {
- dev_err(dev, "Failed to register miscdevice: %d\n", rc);
- ida_simple_remove(&sbefifo_ida, sbefifo->idx);
- return rc;
+ dev_err(dev, "Error %d creating char device %s\n",
+ rc, dev_name(&sbefifo->dev));
+ goto err_free_minor;
}
/* Create platform devs for dts child nodes (occ, etc) */
for_each_available_child_of_node(dev->of_node, np) {
snprintf(child_name, sizeof(child_name), "%s-dev%d",
- sbefifo->name, child_idx++);
+ dev_name(&sbefifo->dev), child_idx++);
child = of_platform_device_create(np, child_name, dev);
if (!child)
dev_warn(dev, "failed to create child %s dev\n",
@@ -948,6 +967,11 @@ static int sbefifo_probe(struct device *dev)
}
return 0;
+ err_free_minor:
+ fsi_free_minor(sbefifo->dev.devt);
+ err:
+ put_device(&sbefifo->dev);
+ return rc;
}
static int sbefifo_unregister_child(struct device *dev, void *data)
@@ -967,10 +991,14 @@ static int sbefifo_remove(struct device *dev)
dev_dbg(dev, "Removing sbefifo device...\n");
- misc_deregister(&sbefifo->mdev);
- device_for_each_child(dev, NULL, sbefifo_unregister_child);
+ mutex_lock(&sbefifo->lock);
+ sbefifo->dead = true;
+ mutex_unlock(&sbefifo->lock);
- ida_simple_remove(&sbefifo_ida, sbefifo->idx);
+ cdev_device_del(&sbefifo->cdev, &sbefifo->dev);
+ fsi_free_minor(sbefifo->dev.devt);
+ device_for_each_child(dev, NULL, sbefifo_unregister_child);
+ put_device(&sbefifo->dev);
return 0;
}
@@ -1001,8 +1029,6 @@ static int sbefifo_init(void)
static void sbefifo_exit(void)
{
fsi_driver_unregister(&sbefifo_drv);
-
- ida_destroy(&sbefifo_ida);
}
module_init(sbefifo_init);
--
2.17.1
^ permalink raw reply related
* [PATCH 3/5] fsi: scom: Convert to use the new chardev
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
This converts FSI scom to use the new fsi-core controlled
chardev allocator and use a real cdev instead of a miscdev.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-scom.c | 130 +++++++++++++++++++++++++----------------
1 file changed, 80 insertions(+), 50 deletions(-)
diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
index 39c74351f1bf..0f303a700f69 100644
--- a/drivers/fsi/fsi-scom.c
+++ b/drivers/fsi/fsi-scom.c
@@ -20,9 +20,8 @@
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
-#include <linux/miscdevice.h>
+#include <linux/cdev.h>
#include <linux/list.h>
-#include <linux/idr.h>
#include <uapi/linux/fsi.h>
@@ -77,18 +76,12 @@
struct scom_device {
struct list_head link;
struct fsi_device *fsi_dev;
- struct miscdevice mdev;
+ struct device dev;
+ struct cdev cdev;
struct mutex lock;
- char name[32];
- int idx;
+ bool dead;
};
-#define to_scom_dev(x) container_of((x), struct scom_device, mdev)
-
-static struct list_head scom_devices;
-
-static DEFINE_IDA(scom_ida);
-
static int __put_scom(struct scom_device *scom_dev, uint64_t value,
uint32_t addr, uint32_t *status)
{
@@ -374,9 +367,7 @@ static int get_scom(struct scom_device *scom, uint64_t *value,
static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
loff_t *offset)
{
- struct miscdevice *mdev =
- (struct miscdevice *)filep->private_data;
- struct scom_device *scom = to_scom_dev(mdev);
+ struct scom_device *scom = filep->private_data;
struct device *dev = &scom->fsi_dev->dev;
uint64_t val;
int rc;
@@ -385,7 +376,10 @@ static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
return -EINVAL;
mutex_lock(&scom->lock);
- rc = get_scom(scom, &val, *offset);
+ if (scom->dead)
+ rc = -ENODEV;
+ else
+ rc = get_scom(scom, &val, *offset);
mutex_unlock(&scom->lock);
if (rc) {
dev_dbg(dev, "get_scom fail:%d\n", rc);
@@ -403,8 +397,7 @@ static ssize_t scom_write(struct file *filep, const char __user *buf,
size_t len, loff_t *offset)
{
int rc;
- struct miscdevice *mdev = filep->private_data;
- struct scom_device *scom = to_scom_dev(mdev);
+ struct scom_device *scom = filep->private_data;
struct device *dev = &scom->fsi_dev->dev;
uint64_t val;
@@ -418,7 +411,10 @@ static ssize_t scom_write(struct file *filep, const char __user *buf,
}
mutex_lock(&scom->lock);
- rc = put_scom(scom, val, *offset);
+ if (scom->dead)
+ rc = -ENODEV;
+ else
+ rc = put_scom(scom, val, *offset);
mutex_unlock(&scom->lock);
if (rc) {
dev_dbg(dev, "put_scom failed with:%d\n", rc);
@@ -532,12 +528,15 @@ static int scom_check(struct scom_device *scom, void __user *argp)
static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct miscdevice *mdev = file->private_data;
- struct scom_device *scom = to_scom_dev(mdev);
+ struct scom_device *scom = file->private_data;
void __user *argp = (void __user *)arg;
int rc = -ENOTTY;
mutex_lock(&scom->lock);
+ if (scom->dead) {
+ mutex_unlock(&scom->lock);
+ return -ENODEV;
+ }
switch(cmd) {
case FSI_SCOM_CHECK:
rc = scom_check(scom, argp);
@@ -556,48 +555,88 @@ static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return rc;
}
+static int scom_open(struct inode *inode, struct file *file)
+{
+ struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
+
+ file->private_data = scom;
+
+ return 0;
+}
+
static const struct file_operations scom_fops = {
.owner = THIS_MODULE,
+ .open = scom_open,
.llseek = scom_llseek,
.read = scom_read,
.write = scom_write,
.unlocked_ioctl = scom_ioctl,
};
+static void scom_free(struct device *dev)
+{
+ struct scom_device *scom = container_of(dev, struct scom_device, dev);
+
+ put_device(&scom->fsi_dev->dev);
+ kfree(scom);
+}
+
static int scom_probe(struct device *dev)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
struct scom_device *scom;
+ int rc, didx;
- scom = devm_kzalloc(dev, sizeof(*scom), GFP_KERNEL);
+ scom = kzalloc(sizeof(*scom), GFP_KERNEL);
if (!scom)
return -ENOMEM;
-
+ dev_set_drvdata(dev, scom);
mutex_init(&scom->lock);
- scom->idx = ida_simple_get(&scom_ida, 1, INT_MAX, GFP_KERNEL);
- snprintf(scom->name, sizeof(scom->name), "scom%d", scom->idx);
- scom->fsi_dev = fsi_dev;
- scom->mdev.minor = MISC_DYNAMIC_MINOR;
- scom->mdev.fops = &scom_fops;
- scom->mdev.name = scom->name;
- scom->mdev.parent = dev;
- list_add(&scom->link, &scom_devices);
-
- return misc_register(&scom->mdev);
+
+ /* Grab a reference to the device (parent of our cdev), we'll drop it later */
+ if (!get_device(dev)) {
+ kfree(scom);
+ return -ENODEV;
+ }
+
+ /* Create chardev for userspace access */
+ scom->dev.type = &fsi_cdev_type;
+ scom->dev.parent = dev;
+ scom->dev.release = scom_free;
+ device_initialize(&scom->dev);
+
+ /* Allocate a minor in the FSI space */
+ rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
+ if (rc)
+ goto err;
+
+ dev_set_name(&scom->dev, "scom%d", didx);
+ cdev_init(&scom->cdev, &scom_fops);
+ rc = cdev_device_add(&scom->cdev, &scom->dev);
+ if (rc) {
+ dev_err(dev, "Error %d creating char device %s\n",
+ rc, dev_name(&scom->dev));
+ goto err_free_minor;
+ }
+
+ return 0;
+ err_free_minor:
+ fsi_free_minor(scom->dev.devt);
+ err:
+ put_device(&scom->dev);
+ return rc;
}
static int scom_remove(struct device *dev)
{
- struct scom_device *scom, *scom_tmp;
- struct fsi_device *fsi_dev = to_fsi_dev(dev);
+ struct scom_device *scom = dev_get_drvdata(dev);
- list_for_each_entry_safe(scom, scom_tmp, &scom_devices, link) {
- if (scom->fsi_dev == fsi_dev) {
- list_del(&scom->link);
- ida_simple_remove(&scom_ida, scom->idx);
- misc_deregister(&scom->mdev);
- }
- }
+ mutex_lock(&scom->lock);
+ scom->dead = true;
+ mutex_unlock(&scom->lock);
+ cdev_device_del(&scom->cdev, &scom->dev);
+ fsi_free_minor(scom->dev.devt);
+ put_device(&scom->dev);
return 0;
}
@@ -622,20 +661,11 @@ static struct fsi_driver scom_drv = {
static int scom_init(void)
{
- INIT_LIST_HEAD(&scom_devices);
return fsi_driver_register(&scom_drv);
}
static void scom_exit(void)
{
- struct list_head *pos;
- struct scom_device *scom;
-
- list_for_each(pos, &scom_devices) {
- scom = list_entry(pos, struct scom_device, link);
- misc_deregister(&scom->mdev);
- devm_kfree(&scom->fsi_dev->dev, scom);
- }
fsi_driver_unregister(&scom_drv);
}
--
2.17.1
^ permalink raw reply related
* [PATCH 4/5] fsi: Add cfam char devices
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
This aims to deprecate the "raw" sysfs file used for directly
accessing the CFAM and instead use a char device like the
other sub drivers.
Since it reworks the slave creation code and adds a cfam device
type, we also use the opportunity to convert the attributes
to attribute groups and add a couple more.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-core.c | 264 +++++++++++++++++++++++++++++++++--------
1 file changed, 213 insertions(+), 51 deletions(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index faa1760a5a40..dea5bd48acc5 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -11,6 +11,11 @@
* 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.
+ *
+ * TODO:
+ * - Rework topology
+ * - s/chip_id/chip_loc
+ * - s/cfam/chip (cfam_id -> chip_id etc...)
*/
#include <linux/crc4.h>
@@ -21,6 +26,9 @@
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/bitops.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
#include "fsi-master.h"
@@ -78,8 +86,11 @@ static DEFINE_IDA(master_ida);
struct fsi_slave {
struct device dev;
struct fsi_master *master;
- int id;
- int link;
+ struct cdev cdev;
+ int cdev_idx;
+ int id; /* FSI address */
+ int link; /* FSI link# */
+ u32 cfam_id;
int chip_id;
uint32_t size; /* size of slave address space */
u8 t_send_delay;
@@ -607,29 +618,6 @@ static const struct bin_attribute fsi_slave_raw_attr = {
.write = fsi_slave_sysfs_raw_write,
};
-static ssize_t fsi_slave_sysfs_term_write(struct file *file,
- struct kobject *kobj, struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
-{
- struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
- struct fsi_master *master = slave->master;
-
- if (!master->term)
- return -ENODEV;
-
- master->term(master, slave->link, slave->id);
- return count;
-}
-
-static const struct bin_attribute fsi_slave_term_attr = {
- .attr = {
- .name = "term",
- .mode = 0200,
- },
- .size = 0,
- .write = fsi_slave_sysfs_term_write,
-};
-
static void fsi_slave_release(struct device *dev)
{
struct fsi_slave *slave = to_fsi_slave(dev);
@@ -682,6 +670,127 @@ static struct device_node *fsi_slave_find_of_node(struct fsi_master *master,
return NULL;
}
+static ssize_t cfam_read(struct file *filep, char __user *buf, size_t count,
+ loff_t *offset)
+{
+ struct fsi_slave *slave = filep->private_data;
+ size_t total_len, read_len;
+ loff_t off = *offset;
+ ssize_t rc;
+
+ if (off < 0)
+ return -EINVAL;
+
+ if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+ return -EINVAL;
+
+ for (total_len = 0; total_len < count; total_len += read_len) {
+ __be32 data;
+
+ read_len = min_t(size_t, count, 4);
+ read_len -= off & 0x3;
+
+ rc = fsi_slave_read(slave, off, &data, read_len);
+ if (rc)
+ goto fail;
+ rc = copy_to_user(buf + total_len, &data, read_len);
+ if (rc) {
+ rc = -EFAULT;
+ goto fail;
+ }
+ off += read_len;
+ }
+ rc = count;
+ fail:
+ *offset = off;
+ return count;
+}
+
+static ssize_t cfam_write(struct file *filep, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct fsi_slave *slave = filep->private_data;
+ size_t total_len, write_len;
+ loff_t off = *offset;
+ ssize_t rc;
+
+
+ if (off < 0)
+ return -EINVAL;
+
+ if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+ return -EINVAL;
+
+ for (total_len = 0; total_len < count; total_len += write_len) {
+ __be32 data;
+
+ write_len = min_t(size_t, count, 4);
+ write_len -= off & 0x3;
+
+ rc = copy_from_user(&data, buf + total_len, write_len);
+ if (rc) {
+ rc = -EFAULT;
+ goto fail;
+ }
+ rc = fsi_slave_write(slave, off, &data, write_len);
+ if (rc)
+ goto fail;
+ off += write_len;
+ }
+ rc = count;
+ fail:
+ *offset = off;
+ return count;
+}
+
+static loff_t cfam_llseek(struct file *file, loff_t offset, int whence)
+{
+ switch (whence) {
+ case SEEK_CUR:
+ break;
+ case SEEK_SET:
+ file->f_pos = offset;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return offset;
+}
+
+static int cfam_open(struct inode *inode, struct file *file)
+{
+ struct fsi_slave *slave = container_of(inode->i_cdev, struct fsi_slave, cdev);
+
+ file->private_data = slave;
+
+ return 0;
+}
+
+static const struct file_operations cfam_fops = {
+ .owner = THIS_MODULE,
+ .open = cfam_open,
+ .llseek = cfam_llseek,
+ .read = cfam_read,
+ .write = cfam_write,
+};
+
+static ssize_t send_term_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+ struct fsi_master *master = slave->master;
+
+ if (!master->term)
+ return -ENODEV;
+
+ master->term(master, slave->link, slave->id);
+ return count;
+}
+
+static DEVICE_ATTR_WO(send_term);
+
static ssize_t slave_send_echo_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -737,6 +846,52 @@ static ssize_t chip_id_show(struct device *dev,
static DEVICE_ATTR_RO(chip_id);
+static ssize_t cfam_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+
+ return sprintf(buf, "0x%x\n", slave->cfam_id);
+}
+
+static DEVICE_ATTR_RO(cfam_id);
+
+static struct attribute *cfam_attr[] = {
+ &dev_attr_send_echo_delays.attr,
+ &dev_attr_chip_id.attr,
+ &dev_attr_cfam_id.attr,
+ &dev_attr_send_term.attr,
+ NULL,
+};
+
+static const struct attribute_group cfam_attr_group = {
+ .attrs = cfam_attr,
+};
+
+static const struct attribute_group *cfam_attr_groups[] = {
+ &cfam_attr_group,
+ NULL,
+};
+
+static char *cfam_devnode(struct device *dev, umode_t *mode,
+ kuid_t *uid, kgid_t *gid)
+{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return kasprintf(GFP_KERNEL, "fsi/cfam%d", slave->cdev_idx);
+#else
+ return kasprintf(GFP_KERNEL, "cfam%d", slave->cdev_idx);
+#endif
+}
+
+static const struct device_type cfam_type = {
+ .name = "cfam",
+ .devnode = cfam_devnode,
+ .groups = cfam_attr_groups
+};
+
static char *fsi_cdev_devnode(struct device *dev, umode_t *mode,
kuid_t *uid, kgid_t *gid)
{
@@ -808,7 +963,7 @@ EXPORT_SYMBOL_GPL(fsi_free_minor);
static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
{
- uint32_t chip_id;
+ uint32_t cfam_id;
struct fsi_slave *slave;
uint8_t crc;
__be32 data, llmode;
@@ -826,17 +981,17 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
link, id, rc);
return -ENODEV;
}
- chip_id = be32_to_cpu(data);
+ cfam_id = be32_to_cpu(data);
- crc = crc4(0, chip_id, 32);
+ crc = crc4(0, cfam_id, 32);
if (crc) {
- dev_warn(&master->dev, "slave %02x:%02x invalid chip id CRC!\n",
+ dev_warn(&master->dev, "slave %02x:%02x invalid cfam id CRC!\n",
link, id);
return -EIO;
}
dev_dbg(&master->dev, "fsi: found chip %08x at %02x:%02x:%02x\n",
- chip_id, master->idx, link, id);
+ cfam_id, master->idx, link, id);
/* If we're behind a master that doesn't provide a self-running bus
* clock, put the slave into async mode
@@ -859,10 +1014,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
if (!slave)
return -ENOMEM;
- slave->master = master;
+ dev_set_name(&slave->dev, "slave@%02x:%02x", link, id);
+ slave->dev.type = &cfam_type;
slave->dev.parent = &master->dev;
slave->dev.of_node = fsi_slave_find_of_node(master, link, id);
slave->dev.release = fsi_slave_release;
+ device_initialize(&slave->dev);
+ slave->cfam_id = cfam_id;
+ slave->master = master;
slave->link = link;
slave->id = id;
slave->size = FSI_SLAVE_SIZE_23b;
@@ -877,6 +1036,21 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
slave->chip_id = prop;
}
+
+ /* Allocate a minor in the FSI space */
+ rc = __fsi_get_new_minor(slave, fsi_dev_cfam, &slave->dev.devt,
+ &slave->cdev_idx);
+ if (rc)
+ goto err_free;
+
+ /* Create chardev for userspace access */
+ cdev_init(&slave->cdev, &cfam_fops);
+ rc = cdev_device_add(&slave->cdev, &slave->dev);
+ if (rc) {
+ dev_err(&slave->dev, "Error %d creating slave device\n", rc);
+ goto err_free;
+ }
+
rc = fsi_slave_set_smode(slave);
if (rc) {
dev_warn(&master->dev,
@@ -890,30 +1064,11 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
slave->t_send_delay,
slave->t_echo_delay);
- dev_set_name(&slave->dev, "slave@%02x:%02x", link, id);
- rc = device_register(&slave->dev);
- if (rc < 0) {
- dev_warn(&master->dev, "failed to create slave device: %d\n",
- rc);
- put_device(&slave->dev);
- return rc;
- }
-
+ /* Legacy raw file -> to be removed */
rc = device_create_bin_file(&slave->dev, &fsi_slave_raw_attr);
if (rc)
dev_warn(&slave->dev, "failed to create raw attr: %d\n", rc);
- rc = device_create_bin_file(&slave->dev, &fsi_slave_term_attr);
- if (rc)
- dev_warn(&slave->dev, "failed to create term attr: %d\n", rc);
-
- rc = device_create_file(&slave->dev, &dev_attr_send_echo_delays);
- if (rc)
- dev_warn(&slave->dev, "failed to create delay attr: %d\n", rc);
-
- rc = device_create_file(&slave->dev, &dev_attr_chip_id);
- if (rc)
- dev_warn(&slave->dev, "failed to create chip id: %d\n", rc);
rc = fsi_slave_scan(slave);
if (rc)
@@ -921,6 +1076,10 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
rc);
return rc;
+
+ err_free:
+ put_device(&slave->dev);
+ return rc;
}
/* FSI master support */
@@ -1029,7 +1188,10 @@ static int fsi_slave_remove_device(struct device *dev, void *arg)
static int fsi_master_remove_slave(struct device *dev, void *arg)
{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+
device_for_each_child(dev, NULL, fsi_slave_remove_device);
+ cdev_device_del(&slave->cdev, &slave->dev);
put_device(dev);
return 0;
}
--
2.17.1
^ permalink raw reply related
* [PATCH 5/5] fsi: Prevent multiple concurrent rescans
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: linux-aspeed
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
The bus scanning process isn't terribly good at parallel attempts
at rescanning the same bus. Let's have a per-master mutex protecting
the scanning process.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-core.c | 16 ++++++++++++++--
drivers/fsi/fsi-master.h | 2 ++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index dea5bd48acc5..2c31563fdcae 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -1203,8 +1203,14 @@ static void fsi_master_unscan(struct fsi_master *master)
int fsi_master_rescan(struct fsi_master *master)
{
+ int rc;
+
+ mutex_lock(&master->scan_lock);
fsi_master_unscan(master);
- return fsi_master_scan(master);
+ rc = fsi_master_scan(master);
+ mutex_unlock(&master->scan_lock);
+
+ return rc;
}
EXPORT_SYMBOL_GPL(fsi_master_rescan);
@@ -1240,6 +1246,7 @@ int fsi_master_register(struct fsi_master *master)
int rc;
struct device_node *np;
+ mutex_init(&master->scan_lock);
master->idx = ida_simple_get(&master_ida, 0, INT_MAX, GFP_KERNEL);
dev_set_name(&master->dev, "fsi%d", master->idx);
@@ -1264,8 +1271,11 @@ int fsi_master_register(struct fsi_master *master)
}
np = dev_of_node(&master->dev);
- if (!of_property_read_bool(np, "no-scan-on-init"))
+ if (!of_property_read_bool(np, "no-scan-on-init")) {
+ mutex_lock(&master->scan_lock);
fsi_master_scan(master);
+ mutex_unlock(&master->scan_lock);
+ }
return 0;
}
@@ -1278,7 +1288,9 @@ void fsi_master_unregister(struct fsi_master *master)
master->idx = -1;
}
+ mutex_lock(&master->scan_lock);
fsi_master_unscan(master);
+ mutex_unlock(&master->scan_lock);
device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(fsi_master_unregister);
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index f653f75da7be..040a7d4cf717 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -18,6 +18,7 @@
#define DRIVERS_FSI_MASTER_H
#include <linux/device.h>
+#include <linux/mutex.h>
/* Various protocol delays */
#define FSI_ECHO_DELAY_CLOCKS 16 /* Number clocks for echo delay */
@@ -59,6 +60,7 @@ struct fsi_master {
int idx;
int n_links;
int flags;
+ struct mutex scan_lock;
int (*read)(struct fsi_master *, int link, uint8_t id,
uint32_t addr, void *val, size_t size);
int (*write)(struct fsi_master *, int link, uint8_t id,
--
2.17.1
^ permalink raw reply related
* [PATCH 0/5] fsi: Convert misc devs to proper chardevs and more
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: openbmc
Cc: Joel Stanley, linux-aspeed, Andrew Jeffery, Eddie James,
Linux Kernel Mailing List
This converts the various FSI devices from misc dev to chardev,
as there can potentially be too much of them for misc devs limited
minors, and because there are some lifetime issues with the current
support.
This provide a common infrastructure to allocate an FSI major and
distribute minors in a way that keeps it compatible with existing
userspace. A new representation grouping FSI devices under a
/dev/fsi directory is optinally provided, which will work in
conjunction with new udev scripts aimed at providing fixed ID
based symlinks.
A side effect of those conversions is to fix some object lifetime
issues caused by a mixup between devm_kzalloc and proper object
lifetime.
This series also adds a /dev{/fsi}/cfamN chardev for raw CFAM
access that will superseed the existing "raw" sysfs file.
Finally there's also a locking fix to avoid horrible mixups if
the "rescan" file is poked while a rescan is already in progress.
^ permalink raw reply
* [PATCH 3/5] fsi: scom: Convert to use the new chardev
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: openbmc
Cc: Joel Stanley, linux-aspeed, Andrew Jeffery, Eddie James,
Linux Kernel Mailing List, Benjamin Herrenschmidt
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
This converts FSI scom to use the new fsi-core controlled
chardev allocator and use a real cdev instead of a miscdev.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-scom.c | 130 +++++++++++++++++++++++++----------------
1 file changed, 80 insertions(+), 50 deletions(-)
diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
index 39c74351f1bf..0f303a700f69 100644
--- a/drivers/fsi/fsi-scom.c
+++ b/drivers/fsi/fsi-scom.c
@@ -20,9 +20,8 @@
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
-#include <linux/miscdevice.h>
+#include <linux/cdev.h>
#include <linux/list.h>
-#include <linux/idr.h>
#include <uapi/linux/fsi.h>
@@ -77,18 +76,12 @@
struct scom_device {
struct list_head link;
struct fsi_device *fsi_dev;
- struct miscdevice mdev;
+ struct device dev;
+ struct cdev cdev;
struct mutex lock;
- char name[32];
- int idx;
+ bool dead;
};
-#define to_scom_dev(x) container_of((x), struct scom_device, mdev)
-
-static struct list_head scom_devices;
-
-static DEFINE_IDA(scom_ida);
-
static int __put_scom(struct scom_device *scom_dev, uint64_t value,
uint32_t addr, uint32_t *status)
{
@@ -374,9 +367,7 @@ static int get_scom(struct scom_device *scom, uint64_t *value,
static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
loff_t *offset)
{
- struct miscdevice *mdev =
- (struct miscdevice *)filep->private_data;
- struct scom_device *scom = to_scom_dev(mdev);
+ struct scom_device *scom = filep->private_data;
struct device *dev = &scom->fsi_dev->dev;
uint64_t val;
int rc;
@@ -385,7 +376,10 @@ static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
return -EINVAL;
mutex_lock(&scom->lock);
- rc = get_scom(scom, &val, *offset);
+ if (scom->dead)
+ rc = -ENODEV;
+ else
+ rc = get_scom(scom, &val, *offset);
mutex_unlock(&scom->lock);
if (rc) {
dev_dbg(dev, "get_scom fail:%d\n", rc);
@@ -403,8 +397,7 @@ static ssize_t scom_write(struct file *filep, const char __user *buf,
size_t len, loff_t *offset)
{
int rc;
- struct miscdevice *mdev = filep->private_data;
- struct scom_device *scom = to_scom_dev(mdev);
+ struct scom_device *scom = filep->private_data;
struct device *dev = &scom->fsi_dev->dev;
uint64_t val;
@@ -418,7 +411,10 @@ static ssize_t scom_write(struct file *filep, const char __user *buf,
}
mutex_lock(&scom->lock);
- rc = put_scom(scom, val, *offset);
+ if (scom->dead)
+ rc = -ENODEV;
+ else
+ rc = put_scom(scom, val, *offset);
mutex_unlock(&scom->lock);
if (rc) {
dev_dbg(dev, "put_scom failed with:%d\n", rc);
@@ -532,12 +528,15 @@ static int scom_check(struct scom_device *scom, void __user *argp)
static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct miscdevice *mdev = file->private_data;
- struct scom_device *scom = to_scom_dev(mdev);
+ struct scom_device *scom = file->private_data;
void __user *argp = (void __user *)arg;
int rc = -ENOTTY;
mutex_lock(&scom->lock);
+ if (scom->dead) {
+ mutex_unlock(&scom->lock);
+ return -ENODEV;
+ }
switch(cmd) {
case FSI_SCOM_CHECK:
rc = scom_check(scom, argp);
@@ -556,48 +555,88 @@ static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return rc;
}
+static int scom_open(struct inode *inode, struct file *file)
+{
+ struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
+
+ file->private_data = scom;
+
+ return 0;
+}
+
static const struct file_operations scom_fops = {
.owner = THIS_MODULE,
+ .open = scom_open,
.llseek = scom_llseek,
.read = scom_read,
.write = scom_write,
.unlocked_ioctl = scom_ioctl,
};
+static void scom_free(struct device *dev)
+{
+ struct scom_device *scom = container_of(dev, struct scom_device, dev);
+
+ put_device(&scom->fsi_dev->dev);
+ kfree(scom);
+}
+
static int scom_probe(struct device *dev)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
struct scom_device *scom;
+ int rc, didx;
- scom = devm_kzalloc(dev, sizeof(*scom), GFP_KERNEL);
+ scom = kzalloc(sizeof(*scom), GFP_KERNEL);
if (!scom)
return -ENOMEM;
-
+ dev_set_drvdata(dev, scom);
mutex_init(&scom->lock);
- scom->idx = ida_simple_get(&scom_ida, 1, INT_MAX, GFP_KERNEL);
- snprintf(scom->name, sizeof(scom->name), "scom%d", scom->idx);
- scom->fsi_dev = fsi_dev;
- scom->mdev.minor = MISC_DYNAMIC_MINOR;
- scom->mdev.fops = &scom_fops;
- scom->mdev.name = scom->name;
- scom->mdev.parent = dev;
- list_add(&scom->link, &scom_devices);
-
- return misc_register(&scom->mdev);
+
+ /* Grab a reference to the device (parent of our cdev), we'll drop it later */
+ if (!get_device(dev)) {
+ kfree(scom);
+ return -ENODEV;
+ }
+
+ /* Create chardev for userspace access */
+ scom->dev.type = &fsi_cdev_type;
+ scom->dev.parent = dev;
+ scom->dev.release = scom_free;
+ device_initialize(&scom->dev);
+
+ /* Allocate a minor in the FSI space */
+ rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
+ if (rc)
+ goto err;
+
+ dev_set_name(&scom->dev, "scom%d", didx);
+ cdev_init(&scom->cdev, &scom_fops);
+ rc = cdev_device_add(&scom->cdev, &scom->dev);
+ if (rc) {
+ dev_err(dev, "Error %d creating char device %s\n",
+ rc, dev_name(&scom->dev));
+ goto err_free_minor;
+ }
+
+ return 0;
+ err_free_minor:
+ fsi_free_minor(scom->dev.devt);
+ err:
+ put_device(&scom->dev);
+ return rc;
}
static int scom_remove(struct device *dev)
{
- struct scom_device *scom, *scom_tmp;
- struct fsi_device *fsi_dev = to_fsi_dev(dev);
+ struct scom_device *scom = dev_get_drvdata(dev);
- list_for_each_entry_safe(scom, scom_tmp, &scom_devices, link) {
- if (scom->fsi_dev == fsi_dev) {
- list_del(&scom->link);
- ida_simple_remove(&scom_ida, scom->idx);
- misc_deregister(&scom->mdev);
- }
- }
+ mutex_lock(&scom->lock);
+ scom->dead = true;
+ mutex_unlock(&scom->lock);
+ cdev_device_del(&scom->cdev, &scom->dev);
+ fsi_free_minor(scom->dev.devt);
+ put_device(&scom->dev);
return 0;
}
@@ -622,20 +661,11 @@ static struct fsi_driver scom_drv = {
static int scom_init(void)
{
- INIT_LIST_HEAD(&scom_devices);
return fsi_driver_register(&scom_drv);
}
static void scom_exit(void)
{
- struct list_head *pos;
- struct scom_device *scom;
-
- list_for_each(pos, &scom_devices) {
- scom = list_entry(pos, struct scom_device, link);
- misc_deregister(&scom->mdev);
- devm_kfree(&scom->fsi_dev->dev, scom);
- }
fsi_driver_unregister(&scom_drv);
}
--
2.17.1
^ permalink raw reply related
* [PATCH 1/5] fsi: Add new central chardev support
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: openbmc
Cc: Joel Stanley, linux-aspeed, Andrew Jeffery, Eddie James,
Linux Kernel Mailing List, Benjamin Herrenschmidt
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
The various FSI devices (sbefifo, occ, scom, more to come)
currently use misc devices.
This is problematic as the minor device space for misc is
limited and there can be a lot of them. Also it limits our
ability to move them to a dedicated /dev/fsi directory or
to be smart about device naming and numbering.
It also means we have IDAs on every single of these drivers
This creates a common fsi "device_type" for the optional
/dev/fsi grouping and a dev_t allocator for all FSI devices.
"Legacy" devices get to use a backward compatible numbering
scheme (as long as chip id <16 and there's only one copy
of a given unit type per chip).
A single major number and a single IDA are shared for all
FSI devices.
This doesn't convert the FSI device drivers to use the new
scheme yet, they will be converted individually.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/Kconfig | 15 +++++++
drivers/fsi/fsi-core.c | 95 +++++++++++++++++++++++++++++++++++++++++-
include/linux/fsi.h | 12 +++++-
3 files changed, 119 insertions(+), 3 deletions(-)
diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index 8d82b1e60514..af3a20dd5aa4 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -12,6 +12,21 @@ menuconfig FSI
if FSI
+config FSI_NEW_DEV_NODE
+ bool "Create '/dev/fsi' directory for char devices"
+ default n
+ ---help---
+ This option causes char devices created for FSI devices to be
+ located under a common /dev/fsi/ directory. Set to N unless your
+ userspace has been updated to handle the new location.
+
+ Additionally, it also causes the char device names to be offset
+ by one so that chip 0 will have /dev/scom1 and chip1 /dev/scom2
+ to match old userspace expectations.
+
+ New userspace will use udev rules to generate predictable access
+ symlinks in /dev/fsi/by-path when this option is enabled.
+
config FSI_MASTER_GPIO
tristate "GPIO-based FSI master"
depends on GPIOLIB
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index eab6c5c4990e..faa1760a5a40 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -92,6 +92,13 @@ struct fsi_slave {
static const int slave_retries = 2;
static int discard_errors;
+static dev_t fsi_base_dev;
+static DEFINE_IDA(fsi_minor_ida);
+#define FSI_CHAR_MAX_DEVICES 0x1000
+
+/* Legacy /dev numbering: 4 devices per chip, 16 chips */
+#define FSI_CHAR_LEGACY_TOP 64
+
static int fsi_master_read(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, void *val, size_t size);
static int fsi_master_write(struct fsi_master *master, int link,
@@ -627,6 +634,7 @@ static void fsi_slave_release(struct device *dev)
{
struct fsi_slave *slave = to_fsi_slave(dev);
+ fsi_free_minor(slave->dev.devt);
of_node_put(dev->of_node);
kfree(slave);
}
@@ -729,6 +737,75 @@ static ssize_t chip_id_show(struct device *dev,
static DEVICE_ATTR_RO(chip_id);
+static char *fsi_cdev_devnode(struct device *dev, umode_t *mode,
+ kuid_t *uid, kgid_t *gid)
+{
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return kasprintf(GFP_KERNEL, "fsi/%s", dev_name(dev));
+#else
+ return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
+#endif
+}
+
+const struct device_type fsi_cdev_type = {
+ .name = "fsi-cdev",
+ .devnode = fsi_cdev_devnode,
+};
+EXPORT_SYMBOL_GPL(fsi_cdev_type);
+
+/* Backward compatible /dev/ numbering in "old style" mode */
+static int fsi_adjust_index(int index)
+{
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return index;
+#else
+ return index + 1;
+#endif
+}
+
+static int __fsi_get_new_minor(struct fsi_slave *slave, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index)
+{
+ int cid = slave->chip_id;
+ int id;
+
+ /* Check if we qualify for legacy numbering */
+ if (cid >= 0 && cid < 16 && type < 4) {
+ /* Try reserving the legacy number */
+ id = (cid << 4) | type;
+ id = ida_simple_get(&fsi_minor_ida, id, id + 1, GFP_KERNEL);
+ if (id >= 0) {
+ *out_index = fsi_adjust_index(cid);
+ *out_dev = fsi_base_dev + id;
+ return 0;
+ }
+ /* Other failure */
+ if (id != -ENOSPC)
+ return id;
+ /* Fallback to non-legacy allocation */
+ }
+ id = ida_simple_get(&fsi_minor_ida, FSI_CHAR_LEGACY_TOP,
+ FSI_CHAR_MAX_DEVICES, GFP_KERNEL);
+ if (id < 0)
+ return id;
+ *out_index = fsi_adjust_index(id);
+ *out_dev = fsi_base_dev + id;
+ return 0;
+}
+
+int fsi_get_new_minor(struct fsi_device *fdev, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index)
+{
+ return __fsi_get_new_minor(fdev->slave, type, out_dev, out_index);
+}
+EXPORT_SYMBOL_GPL(fsi_get_new_minor);
+
+void fsi_free_minor(dev_t dev)
+{
+ ida_simple_remove(&fsi_minor_ida, MINOR(dev));
+}
+EXPORT_SYMBOL_GPL(fsi_free_minor);
+
static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
{
uint32_t chip_id;
@@ -953,7 +1030,7 @@ static int fsi_slave_remove_device(struct device *dev, void *arg)
static int fsi_master_remove_slave(struct device *dev, void *arg)
{
device_for_each_child(dev, NULL, fsi_slave_remove_device);
- device_unregister(dev);
+ put_device(dev);
return 0;
}
@@ -1091,13 +1168,27 @@ EXPORT_SYMBOL_GPL(fsi_bus_type);
static int __init fsi_init(void)
{
- return bus_register(&fsi_bus_type);
+ int rc;
+
+ rc = alloc_chrdev_region(&fsi_base_dev, 0, FSI_CHAR_MAX_DEVICES, "fsi");
+ if (rc)
+ return rc;
+ rc = bus_register(&fsi_bus_type);
+ if (rc)
+ goto fail_bus;
+ return 0;
+
+ fail_bus:
+ unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES);
+ return rc;
}
postcore_initcall(fsi_init);
static void fsi_exit(void)
{
bus_unregister(&fsi_bus_type);
+ unregister_chrdev_region(fsi_base_dev, FSI_CHAR_MAX_DEVICES);
+ ida_destroy(&fsi_minor_ida);
}
module_exit(fsi_exit);
module_param(discard_errors, int, 0664);
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 141fd38d061f..ec3be0d5b786 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -76,8 +76,18 @@ extern int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
extern int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
const void *val, size_t size);
+extern struct bus_type fsi_bus_type;
+extern const struct device_type fsi_cdev_type;
+enum fsi_dev_type {
+ fsi_dev_cfam,
+ fsi_dev_sbefifo,
+ fsi_dev_scom,
+ fsi_dev_occ
+};
-extern struct bus_type fsi_bus_type;
+extern int fsi_get_new_minor(struct fsi_device *fdev, enum fsi_dev_type type,
+ dev_t *out_dev, int *out_index);
+extern void fsi_free_minor(dev_t dev);
#endif /* LINUX_FSI_H */
--
2.17.1
^ permalink raw reply related
* [PATCH 2/5] fsi: sbefifo: Convert to use the new chardev
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: openbmc
Cc: Joel Stanley, linux-aspeed, Andrew Jeffery, Eddie James,
Linux Kernel Mailing List, Benjamin Herrenschmidt
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
This converts FSI sbefifo to use the new fsi-core controlled
chardev allocator and use a real cdev instead of a miscdev.
One side effect is to fix the object lifetime by removing
the use of devm_kzalloc() for something that contains kobjects,
and using proper reference counting.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-sbefifo.c | 84 +++++++++++++++++++++++++--------------
1 file changed, 55 insertions(+), 29 deletions(-)
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 33a5d9a43a07..8a185f53c9d8 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -17,9 +17,8 @@
#include <linux/fs.h>
#include <linux/fsi.h>
#include <linux/fsi-sbefifo.h>
-#include <linux/idr.h>
#include <linux/kernel.h>
-#include <linux/miscdevice.h>
+#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
@@ -118,11 +117,11 @@ struct sbefifo {
uint32_t magic;
#define SBEFIFO_MAGIC 0x53424546 /* "SBEF" */
struct fsi_device *fsi_dev;
- struct miscdevice mdev;
+ struct device dev;
+ struct cdev cdev;
struct mutex lock;
- char name[32];
- int idx;
bool broken;
+ bool dead;
bool async_ffdc;
};
@@ -133,9 +132,9 @@ struct sbefifo_user {
size_t pending_len;
};
-static DEFINE_IDA(sbefifo_ida);
static DEFINE_MUTEX(sbefifo_ffdc_mutex);
+
static void __sbefifo_dump_ffdc(struct device *dev, const __be32 *ffdc,
size_t ffdc_sz, bool internal)
{
@@ -667,6 +666,9 @@ static int __sbefifo_submit(struct sbefifo *sbefifo,
struct device *dev = &sbefifo->fsi_dev->dev;
int rc;
+ if (sbefifo->dead)
+ return -ENODEV;
+
if (cmd_len < 2 || be32_to_cpu(command[0]) != cmd_len) {
dev_vdbg(dev, "Invalid command len %zd (header: %d)\n",
cmd_len, be32_to_cpu(command[0]));
@@ -751,8 +753,7 @@ EXPORT_SYMBOL_GPL(sbefifo_submit);
*/
static int sbefifo_user_open(struct inode *inode, struct file *file)
{
- struct sbefifo *sbefifo = container_of(file->private_data,
- struct sbefifo, mdev);
+ struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev);
struct sbefifo_user *user;
user = kzalloc(sizeof(struct sbefifo_user), GFP_KERNEL);
@@ -889,6 +890,14 @@ static const struct file_operations sbefifo_fops = {
.release = sbefifo_user_release,
};
+static void sbefifo_free(struct device *dev)
+{
+ struct sbefifo *sbefifo = container_of(dev, struct sbefifo, dev);
+
+ put_device(&sbefifo->fsi_dev->dev);
+ kfree(sbefifo);
+}
+
/*
* Probe/remove
*/
@@ -900,15 +909,23 @@ static int sbefifo_probe(struct device *dev)
struct device_node *np;
struct platform_device *child;
char child_name[32];
- int rc, child_idx = 0;
+ int rc, didx, child_idx = 0;
dev_dbg(dev, "Found sbefifo device\n");
- sbefifo = devm_kzalloc(dev, sizeof(*sbefifo), GFP_KERNEL);
+ sbefifo = kzalloc(sizeof(*sbefifo), GFP_KERNEL);
if (!sbefifo)
return -ENOMEM;
+
+ /* Grab a reference to the device (parent of our cdev), we'll drop it later */
+ if (!get_device(dev)) {
+ return -ENODEV;
+ kfree(sbefifo);
+ }
+
sbefifo->magic = SBEFIFO_MAGIC;
sbefifo->fsi_dev = fsi_dev;
+ dev_set_drvdata(dev, sbefifo);
mutex_init(&sbefifo->lock);
/*
@@ -919,28 +936,30 @@ static int sbefifo_probe(struct device *dev)
if (rc && rc != -ESHUTDOWN)
dev_err(dev, "Initial HW cleanup failed, will retry later\n");
- sbefifo->idx = ida_simple_get(&sbefifo_ida, 1, INT_MAX, GFP_KERNEL);
- snprintf(sbefifo->name, sizeof(sbefifo->name), "sbefifo%d",
- sbefifo->idx);
+ /* Create chardev for userspace access */
+ sbefifo->dev.type = &fsi_cdev_type;
+ sbefifo->dev.parent = dev;
+ sbefifo->dev.release = sbefifo_free;
+ device_initialize(&sbefifo->dev);
- dev_set_drvdata(dev, sbefifo);
+ /* Allocate a minor in the FSI space */
+ rc = fsi_get_new_minor(fsi_dev, fsi_dev_sbefifo, &sbefifo->dev.devt, &didx);
+ if (rc)
+ goto err;
- /* Create misc chardev for userspace access */
- sbefifo->mdev.minor = MISC_DYNAMIC_MINOR;
- sbefifo->mdev.fops = &sbefifo_fops;
- sbefifo->mdev.name = sbefifo->name;
- sbefifo->mdev.parent = dev;
- rc = misc_register(&sbefifo->mdev);
+ dev_set_name(&sbefifo->dev, "sbefifo%d", didx);
+ cdev_init(&sbefifo->cdev, &sbefifo_fops);
+ rc = cdev_device_add(&sbefifo->cdev, &sbefifo->dev);
if (rc) {
- dev_err(dev, "Failed to register miscdevice: %d\n", rc);
- ida_simple_remove(&sbefifo_ida, sbefifo->idx);
- return rc;
+ dev_err(dev, "Error %d creating char device %s\n",
+ rc, dev_name(&sbefifo->dev));
+ goto err_free_minor;
}
/* Create platform devs for dts child nodes (occ, etc) */
for_each_available_child_of_node(dev->of_node, np) {
snprintf(child_name, sizeof(child_name), "%s-dev%d",
- sbefifo->name, child_idx++);
+ dev_name(&sbefifo->dev), child_idx++);
child = of_platform_device_create(np, child_name, dev);
if (!child)
dev_warn(dev, "failed to create child %s dev\n",
@@ -948,6 +967,11 @@ static int sbefifo_probe(struct device *dev)
}
return 0;
+ err_free_minor:
+ fsi_free_minor(sbefifo->dev.devt);
+ err:
+ put_device(&sbefifo->dev);
+ return rc;
}
static int sbefifo_unregister_child(struct device *dev, void *data)
@@ -967,10 +991,14 @@ static int sbefifo_remove(struct device *dev)
dev_dbg(dev, "Removing sbefifo device...\n");
- misc_deregister(&sbefifo->mdev);
- device_for_each_child(dev, NULL, sbefifo_unregister_child);
+ mutex_lock(&sbefifo->lock);
+ sbefifo->dead = true;
+ mutex_unlock(&sbefifo->lock);
- ida_simple_remove(&sbefifo_ida, sbefifo->idx);
+ cdev_device_del(&sbefifo->cdev, &sbefifo->dev);
+ fsi_free_minor(sbefifo->dev.devt);
+ device_for_each_child(dev, NULL, sbefifo_unregister_child);
+ put_device(&sbefifo->dev);
return 0;
}
@@ -1001,8 +1029,6 @@ static int sbefifo_init(void)
static void sbefifo_exit(void)
{
fsi_driver_unregister(&sbefifo_drv);
-
- ida_destroy(&sbefifo_ida);
}
module_init(sbefifo_init);
--
2.17.1
^ permalink raw reply related
* [PATCH 4/5] fsi: Add cfam char devices
From: Benjamin Herrenschmidt @ 2018-07-24 5:05 UTC (permalink / raw)
To: openbmc
Cc: Joel Stanley, linux-aspeed, Andrew Jeffery, Eddie James,
Linux Kernel Mailing List, Benjamin Herrenschmidt
In-Reply-To: <20180724050519.31920-1-benh@kernel.crashing.org>
This aims to deprecate the "raw" sysfs file used for directly
accessing the CFAM and instead use a char device like the
other sub drivers.
Since it reworks the slave creation code and adds a cfam device
type, we also use the opportunity to convert the attributes
to attribute groups and add a couple more.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/fsi/fsi-core.c | 264 +++++++++++++++++++++++++++++++++--------
1 file changed, 213 insertions(+), 51 deletions(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index faa1760a5a40..dea5bd48acc5 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -11,6 +11,11 @@
* 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.
+ *
+ * TODO:
+ * - Rework topology
+ * - s/chip_id/chip_loc
+ * - s/cfam/chip (cfam_id -> chip_id etc...)
*/
#include <linux/crc4.h>
@@ -21,6 +26,9 @@
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/bitops.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
#include "fsi-master.h"
@@ -78,8 +86,11 @@ static DEFINE_IDA(master_ida);
struct fsi_slave {
struct device dev;
struct fsi_master *master;
- int id;
- int link;
+ struct cdev cdev;
+ int cdev_idx;
+ int id; /* FSI address */
+ int link; /* FSI link# */
+ u32 cfam_id;
int chip_id;
uint32_t size; /* size of slave address space */
u8 t_send_delay;
@@ -607,29 +618,6 @@ static const struct bin_attribute fsi_slave_raw_attr = {
.write = fsi_slave_sysfs_raw_write,
};
-static ssize_t fsi_slave_sysfs_term_write(struct file *file,
- struct kobject *kobj, struct bin_attribute *attr,
- char *buf, loff_t off, size_t count)
-{
- struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
- struct fsi_master *master = slave->master;
-
- if (!master->term)
- return -ENODEV;
-
- master->term(master, slave->link, slave->id);
- return count;
-}
-
-static const struct bin_attribute fsi_slave_term_attr = {
- .attr = {
- .name = "term",
- .mode = 0200,
- },
- .size = 0,
- .write = fsi_slave_sysfs_term_write,
-};
-
static void fsi_slave_release(struct device *dev)
{
struct fsi_slave *slave = to_fsi_slave(dev);
@@ -682,6 +670,127 @@ static struct device_node *fsi_slave_find_of_node(struct fsi_master *master,
return NULL;
}
+static ssize_t cfam_read(struct file *filep, char __user *buf, size_t count,
+ loff_t *offset)
+{
+ struct fsi_slave *slave = filep->private_data;
+ size_t total_len, read_len;
+ loff_t off = *offset;
+ ssize_t rc;
+
+ if (off < 0)
+ return -EINVAL;
+
+ if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+ return -EINVAL;
+
+ for (total_len = 0; total_len < count; total_len += read_len) {
+ __be32 data;
+
+ read_len = min_t(size_t, count, 4);
+ read_len -= off & 0x3;
+
+ rc = fsi_slave_read(slave, off, &data, read_len);
+ if (rc)
+ goto fail;
+ rc = copy_to_user(buf + total_len, &data, read_len);
+ if (rc) {
+ rc = -EFAULT;
+ goto fail;
+ }
+ off += read_len;
+ }
+ rc = count;
+ fail:
+ *offset = off;
+ return count;
+}
+
+static ssize_t cfam_write(struct file *filep, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct fsi_slave *slave = filep->private_data;
+ size_t total_len, write_len;
+ loff_t off = *offset;
+ ssize_t rc;
+
+
+ if (off < 0)
+ return -EINVAL;
+
+ if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+ return -EINVAL;
+
+ for (total_len = 0; total_len < count; total_len += write_len) {
+ __be32 data;
+
+ write_len = min_t(size_t, count, 4);
+ write_len -= off & 0x3;
+
+ rc = copy_from_user(&data, buf + total_len, write_len);
+ if (rc) {
+ rc = -EFAULT;
+ goto fail;
+ }
+ rc = fsi_slave_write(slave, off, &data, write_len);
+ if (rc)
+ goto fail;
+ off += write_len;
+ }
+ rc = count;
+ fail:
+ *offset = off;
+ return count;
+}
+
+static loff_t cfam_llseek(struct file *file, loff_t offset, int whence)
+{
+ switch (whence) {
+ case SEEK_CUR:
+ break;
+ case SEEK_SET:
+ file->f_pos = offset;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return offset;
+}
+
+static int cfam_open(struct inode *inode, struct file *file)
+{
+ struct fsi_slave *slave = container_of(inode->i_cdev, struct fsi_slave, cdev);
+
+ file->private_data = slave;
+
+ return 0;
+}
+
+static const struct file_operations cfam_fops = {
+ .owner = THIS_MODULE,
+ .open = cfam_open,
+ .llseek = cfam_llseek,
+ .read = cfam_read,
+ .write = cfam_write,
+};
+
+static ssize_t send_term_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+ struct fsi_master *master = slave->master;
+
+ if (!master->term)
+ return -ENODEV;
+
+ master->term(master, slave->link, slave->id);
+ return count;
+}
+
+static DEVICE_ATTR_WO(send_term);
+
static ssize_t slave_send_echo_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -737,6 +846,52 @@ static ssize_t chip_id_show(struct device *dev,
static DEVICE_ATTR_RO(chip_id);
+static ssize_t cfam_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+
+ return sprintf(buf, "0x%x\n", slave->cfam_id);
+}
+
+static DEVICE_ATTR_RO(cfam_id);
+
+static struct attribute *cfam_attr[] = {
+ &dev_attr_send_echo_delays.attr,
+ &dev_attr_chip_id.attr,
+ &dev_attr_cfam_id.attr,
+ &dev_attr_send_term.attr,
+ NULL,
+};
+
+static const struct attribute_group cfam_attr_group = {
+ .attrs = cfam_attr,
+};
+
+static const struct attribute_group *cfam_attr_groups[] = {
+ &cfam_attr_group,
+ NULL,
+};
+
+static char *cfam_devnode(struct device *dev, umode_t *mode,
+ kuid_t *uid, kgid_t *gid)
+{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+
+#ifdef CONFIG_FSI_NEW_DEV_NODE
+ return kasprintf(GFP_KERNEL, "fsi/cfam%d", slave->cdev_idx);
+#else
+ return kasprintf(GFP_KERNEL, "cfam%d", slave->cdev_idx);
+#endif
+}
+
+static const struct device_type cfam_type = {
+ .name = "cfam",
+ .devnode = cfam_devnode,
+ .groups = cfam_attr_groups
+};
+
static char *fsi_cdev_devnode(struct device *dev, umode_t *mode,
kuid_t *uid, kgid_t *gid)
{
@@ -808,7 +963,7 @@ EXPORT_SYMBOL_GPL(fsi_free_minor);
static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
{
- uint32_t chip_id;
+ uint32_t cfam_id;
struct fsi_slave *slave;
uint8_t crc;
__be32 data, llmode;
@@ -826,17 +981,17 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
link, id, rc);
return -ENODEV;
}
- chip_id = be32_to_cpu(data);
+ cfam_id = be32_to_cpu(data);
- crc = crc4(0, chip_id, 32);
+ crc = crc4(0, cfam_id, 32);
if (crc) {
- dev_warn(&master->dev, "slave %02x:%02x invalid chip id CRC!\n",
+ dev_warn(&master->dev, "slave %02x:%02x invalid cfam id CRC!\n",
link, id);
return -EIO;
}
dev_dbg(&master->dev, "fsi: found chip %08x at %02x:%02x:%02x\n",
- chip_id, master->idx, link, id);
+ cfam_id, master->idx, link, id);
/* If we're behind a master that doesn't provide a self-running bus
* clock, put the slave into async mode
@@ -859,10 +1014,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
if (!slave)
return -ENOMEM;
- slave->master = master;
+ dev_set_name(&slave->dev, "slave@%02x:%02x", link, id);
+ slave->dev.type = &cfam_type;
slave->dev.parent = &master->dev;
slave->dev.of_node = fsi_slave_find_of_node(master, link, id);
slave->dev.release = fsi_slave_release;
+ device_initialize(&slave->dev);
+ slave->cfam_id = cfam_id;
+ slave->master = master;
slave->link = link;
slave->id = id;
slave->size = FSI_SLAVE_SIZE_23b;
@@ -877,6 +1036,21 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
slave->chip_id = prop;
}
+
+ /* Allocate a minor in the FSI space */
+ rc = __fsi_get_new_minor(slave, fsi_dev_cfam, &slave->dev.devt,
+ &slave->cdev_idx);
+ if (rc)
+ goto err_free;
+
+ /* Create chardev for userspace access */
+ cdev_init(&slave->cdev, &cfam_fops);
+ rc = cdev_device_add(&slave->cdev, &slave->dev);
+ if (rc) {
+ dev_err(&slave->dev, "Error %d creating slave device\n", rc);
+ goto err_free;
+ }
+
rc = fsi_slave_set_smode(slave);
if (rc) {
dev_warn(&master->dev,
@@ -890,30 +1064,11 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
slave->t_send_delay,
slave->t_echo_delay);
- dev_set_name(&slave->dev, "slave@%02x:%02x", link, id);
- rc = device_register(&slave->dev);
- if (rc < 0) {
- dev_warn(&master->dev, "failed to create slave device: %d\n",
- rc);
- put_device(&slave->dev);
- return rc;
- }
-
+ /* Legacy raw file -> to be removed */
rc = device_create_bin_file(&slave->dev, &fsi_slave_raw_attr);
if (rc)
dev_warn(&slave->dev, "failed to create raw attr: %d\n", rc);
- rc = device_create_bin_file(&slave->dev, &fsi_slave_term_attr);
- if (rc)
- dev_warn(&slave->dev, "failed to create term attr: %d\n", rc);
-
- rc = device_create_file(&slave->dev, &dev_attr_send_echo_delays);
- if (rc)
- dev_warn(&slave->dev, "failed to create delay attr: %d\n", rc);
-
- rc = device_create_file(&slave->dev, &dev_attr_chip_id);
- if (rc)
- dev_warn(&slave->dev, "failed to create chip id: %d\n", rc);
rc = fsi_slave_scan(slave);
if (rc)
@@ -921,6 +1076,10 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
rc);
return rc;
+
+ err_free:
+ put_device(&slave->dev);
+ return rc;
}
/* FSI master support */
@@ -1029,7 +1188,10 @@ static int fsi_slave_remove_device(struct device *dev, void *arg)
static int fsi_master_remove_slave(struct device *dev, void *arg)
{
+ struct fsi_slave *slave = to_fsi_slave(dev);
+
device_for_each_child(dev, NULL, fsi_slave_remove_device);
+ cdev_device_del(&slave->cdev, &slave->dev);
put_device(dev);
return 0;
}
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v3 bpf-next 6/8] xdp: Add a flag for disabling napi_direct of xdp_return_frame in xdp_mem_info
From: Toshiaki Makita @ 2018-07-24 4:02 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Toshiaki Makita, netdev, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer
In-Reply-To: <20180723203814.009d661d@cakuba.netronome.com>
On 2018/07/24 12:38, Jakub Kicinski wrote:
> On Tue, 24 Jul 2018 11:43:11 +0900, Toshiaki Makita wrote:
>> On 2018/07/24 10:22, Jakub Kicinski wrote:
>>> On Mon, 23 Jul 2018 00:13:06 +0900, Toshiaki Makita wrote:
>>>> From: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
>>>>
>>>> We need some mechanism to disable napi_direct on calling
>>>> xdp_return_frame_rx_napi() from some context.
>>>> When veth gets support of XDP_REDIRECT, it will redirects packets which
>>>> are redirected from other devices. On redirection veth will reuse
>>>> xdp_mem_info of the redirection source device to make return_frame work.
>>>> But in this case .ndo_xdp_xmit() called from veth redirection uses
>>>> xdp_mem_info which is not guarded by NAPI, because the .ndo_xdp_xmit is
>>>> not called directly from the rxq which owns the xdp_mem_info.
>>>>
>>>> This approach introduces a flag in xdp_mem_info to indicate that
>>>> napi_direct should be disabled even when _rx_napi variant is used.
>>>>
>>>> Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
>>>
>>> To be clear - you will modify flags of the original source device if it
>>> ever redirected a frame to a software device like veth? Seems a bit
>>> heavy handed. The xdp_return_frame_rx_napi() is only really used on
>>> error paths, but still.. Also as you note the original NAPI can run
>>> concurrently with your veth dest one, but also with NAPIs of other veth
>>> devices, so the non-atomic xdp.rxq->mem.flags |= XDP_MEM_RF_NO_DIRECT;
>>> makes me worried.
>>
>> xdp_mem_info is copied in xdp_frame in convert_to_xdp_frame() so the
>> field is local to the frame. Changing flags affects only the frame.
>> xdp.rxq is local to NAPI thread, so no worries about atomicity.
>
> Ah, right! mem_info used to be just 8B, now it would be 12B.
> Alternatively we could perhaps add this info to struct redirect_info,
> through xdp_do_redirect() to avoid the per-frame cost. I'm not sure
> that's better.
OK, let me check if this works.
--
Toshiaki Makita
^ permalink raw reply
* [linux-4.14 test] 125509: regressions - trouble: broken/fail/pass
From: osstest service owner @ 2018-07-24 5:10 UTC (permalink / raw)
To: xen-devel, osstest-admin
flight 125509 linux-4.14 real [real]
http://logs.test-lab.xenproject.org/osstest/logs/125509/
Regressions :-(
Tests which did not succeed and are blocking,
including tests which could not be run:
test-armhf-armhf-xl-credit2 <job status> broken
test-armhf-armhf-xl-credit2 4 host-install(4) broken REGR. vs. 125175
test-amd64-amd64-xl-qemuu-debianhvm-amd64-shadow 10 debian-hvm-install fail REGR. vs. 125175
test-amd64-amd64-xl-qemuu-debianhvm-amd64-xsm 10 debian-hvm-install fail REGR. vs. 125175
test-amd64-i386-qemut-rhel6hvm-amd 10 redhat-install fail REGR. vs. 125175
test-amd64-amd64-xl-pvhv2-amd 10 debian-install fail REGR. vs. 125175
test-amd64-amd64-xl-pvshim 10 debian-install fail REGR. vs. 125175
test-amd64-i386-xl 10 debian-install fail REGR. vs. 125175
Tests which did not succeed, but are not blocking:
test-amd64-i386-xl-qemuu-dmrestrict-amd64-dmrestrict 10 debian-hvm-install fail never pass
test-amd64-amd64-xl-qemuu-dmrestrict-amd64-dmrestrict 10 debian-hvm-install fail never pass
test-amd64-i386-libvirt 13 migrate-support-check fail never pass
test-amd64-i386-libvirt-xsm 13 migrate-support-check fail never pass
test-amd64-amd64-libvirt-xsm 13 migrate-support-check fail never pass
test-amd64-i386-xl-pvshim 12 guest-start fail never pass
test-amd64-amd64-libvirt 13 migrate-support-check fail never pass
test-arm64-arm64-xl 13 migrate-support-check fail never pass
test-arm64-arm64-xl 14 saverestore-support-check fail never pass
test-arm64-arm64-libvirt-xsm 13 migrate-support-check fail never pass
test-arm64-arm64-libvirt-xsm 14 saverestore-support-check fail never pass
test-arm64-arm64-xl-credit2 13 migrate-support-check fail never pass
test-arm64-arm64-xl-credit2 14 saverestore-support-check fail never pass
test-arm64-arm64-xl-xsm 13 migrate-support-check fail never pass
test-arm64-arm64-xl-xsm 14 saverestore-support-check fail never pass
test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm 11 migrate-support-check fail never pass
test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsm 11 migrate-support-check fail never pass
test-armhf-armhf-xl-arndale 13 migrate-support-check fail never pass
test-armhf-armhf-xl-arndale 14 saverestore-support-check fail never pass
test-amd64-amd64-qemuu-nested-amd 17 debian-hvm-install/l1/l2 fail never pass
test-amd64-amd64-libvirt-vhd 12 migrate-support-check fail never pass
test-armhf-armhf-xl 13 migrate-support-check fail never pass
test-armhf-armhf-xl-multivcpu 13 migrate-support-check fail never pass
test-armhf-armhf-xl-multivcpu 14 saverestore-support-check fail never pass
test-armhf-armhf-xl 14 saverestore-support-check fail never pass
test-armhf-armhf-xl-rtds 13 migrate-support-check fail never pass
test-armhf-armhf-xl-rtds 14 saverestore-support-check fail never pass
test-armhf-armhf-libvirt 13 migrate-support-check fail never pass
test-armhf-armhf-libvirt 14 saverestore-support-check fail never pass
test-armhf-armhf-xl-cubietruck 13 migrate-support-check fail never pass
test-armhf-armhf-xl-cubietruck 14 saverestore-support-check fail never pass
test-amd64-i386-xl-qemut-win7-amd64 17 guest-stop fail never pass
test-amd64-amd64-xl-qemuu-ws16-amd64 17 guest-stop fail never pass
test-amd64-amd64-xl-qemuu-win7-amd64 17 guest-stop fail never pass
test-amd64-i386-xl-qemuu-win7-amd64 17 guest-stop fail never pass
test-armhf-armhf-libvirt-raw 12 migrate-support-check fail never pass
test-armhf-armhf-libvirt-raw 13 saverestore-support-check fail never pass
test-amd64-amd64-xl-qemut-win7-amd64 17 guest-stop fail never pass
test-amd64-i386-xl-qemuu-ws16-amd64 17 guest-stop fail never pass
test-amd64-amd64-xl-qemut-ws16-amd64 17 guest-stop fail never pass
test-amd64-i386-xl-qemut-ws16-amd64 17 guest-stop fail never pass
test-armhf-armhf-xl-vhd 12 migrate-support-check fail never pass
test-armhf-armhf-xl-vhd 13 saverestore-support-check fail never pass
test-amd64-i386-xl-qemut-win10-i386 10 windows-install fail never pass
test-amd64-amd64-xl-qemut-win10-i386 10 windows-install fail never pass
test-amd64-amd64-xl-qemuu-win10-i386 10 windows-install fail never pass
test-amd64-i386-xl-qemuu-win10-i386 10 windows-install fail never pass
version targeted for testing:
linux ecc160ece609498c946e73710e5c7c54c62b966a
baseline version:
linux 1e92e813554a93741666e9f378a83d70405b9076
Last test of basis 125175 2018-07-15 08:04:36 Z 8 days
Failing since 125270 2018-07-17 10:10:13 Z 6 days 5 attempts
Testing same since 125509 2018-07-22 20:11:58 Z 1 days 1 attempts
------------------------------------------------------------
People who touched revisions under test:
Alan Jenkins <alan.christopher.jenkins@gmail.com>
Aleksander Morgado <aleksander@aleksander.es>
Alex Chen <alex.chen@huawei.com>
Alex Vesker <valex@mellanox.com>
Amit Pundir <amit.pundir@linaro.org>
Andreas Schwab <schwab@linux-m68k.org>
Andrew Morton <akpm@linux-foundation.org>
Anna Schumaker <Anna.Schumaker@Netapp.com>
Antoine Tenart <antoine.tenart@bootlin.com>
Ard Biesheuvel <ard.biesheuvel@linaro.org>
Artem Bityutskiy <artem.bityutskiy@intel.com>
Bhadram Varka <vbhadram@nvidia.com>
Bjorn Helgaas <bhelgaas@google.com>
Bjørn Mork <bjorn@mork.no>
Boris Brezillon <boris.brezillon@bootlin.com>
Catalin Marinas <catalin.marinas@arm.com>
Changwei Ge <ge.changwei@h3c.com>
Chris Wilson <chris@chris-wilson.co.uk>
Christian Borntraeger <borntraeger@de.ibm.com>
Christian Brauner <christian.brauner@ubuntu.com>
Christian Lamparter <chunkeey@googlemail.com>
Christoffer Dall <cdall@linaro.org>
Christoffer Dall <christoffer.dall@arm.com>
Christoffer Dall <christoffer.dall@linaro.org>
Christoph Hellwig <hch@lst.de>
Chuck Lever <chuck.lever@oracle.com>
Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Damien Le Moal <damien.lemoal@wdc.com>
Dan Carpenter <dan.carpenter@oracle.com>
Dave Watson <davejwatson@fb.com>
David Ahern <dsahern@gmail.com>
David S. Miller <davem@davemloft.net>
David Sterba <dsterba@suse.com>
David Woodhouse <dwmw2@infradead.org>
Dennis Dalessandro <dennis.dalessandro@intel.com>
Dexuan Cui <decui@microsoft.com>
Diego Viola <diego.viola@gmail.com>
Doron Roberts-Kedes <doronrk@fb.com>
Eli Cohen <eli@mellanox.com>
Eli Cohen <eli@melloanox.com>
Eric Biggers <ebiggers@google.com>
Eric Dumazet <edumazet@google.com>
Evgeny Kapun <abacabadabacaba@gmail.com> # 8723DE
Filipe Manana <fdmanana@suse.com>
Florian Westphal <fw@strlen.de>
Floris Bos <bos@je-eigen-domein.nl>
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Gustavo A. R. Silva <gustavo@embeddedor.com>
H. Peter Anvin <hpa@linux.intel.com>
Haiyang Zhang <haiyangz@microsoft.com>
Hans de Goede <hdegoede@redhat.com>
Harini Katakam <harini.katakam@xilinx.com>
Herbert Xu <herbert@gondor.apana.org.au>
Hui Wang <hui.wang@canonical.com>
Ian Kent <raven@themaw.net>
Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Ingo Molnar <mingo@kernel.org>
Jaegeuk Kim <jaegeuk@kernel.org>
Jaehoon Chung <jh80.chung@samsung.com>
James Morse <james.morse@arm.com>
Jan Kara <jack@suse.cz>
Jann Horn <jannh@google.com>
Jason Gunthorpe <jgg@mellanox.com>
Jason Wang <jasowang@redhat.com>
Jens Axboe <axboe@kernel.dk>
Jesper Dangaard Brouer <brouer@redhat.com>
Jian-Hong Pan <jian-hong@endlessm.com>
Jiri Benc <jbenc@redhat.com>
Jiri Slaby <jslaby@suse.cz>
Joel Fernandes (Google) <joel@joelfernandes.org>
Johan Hovold <johan@kernel.org>
Jon Hunter <jonathanh@nvidia.com>
Jonas Gorski <jonas.gorski@gmail.com>
Jordan Glover <Golden_Miller83@protonmail.ch>
Juergen Gross <jgross@suse.com>
Kai Chieh Chuang <kaichieh.chuang@mediatek.com>
KaiChieh Chuang <kaichieh.chuang@mediatek.com>
Kalle Valo <kvalo@codeaurora.org>
Kashyap Desai <kashyap.desai@broadcom.com>
Kees Cook <keescook@chromium.org>
Keith Busch <keith.busch@intel.com>
Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Leon Romanovsky <leonro@mellanox.com>
Linus Torvalds <torvalds@linux-foundation.org>
Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Marc Zyngier <marc.zyngier@arm.com>
Mark Brown <broonie@kernel.org>
Martin K. Petersen <martin.petersen@oracle.com>
Masahiro Yamada <yamada.masahiro@socionext.com>
Mathias Nyman <mathias.nyman@linux.intel.com>
Mauro Carvalho Chehab <mchehab@s-opensource.com>
Michael J. Ruhl <michael.j.ruhl@intel.com>
Michal Hocko <mhocko@suse.com>
Michal Kalderon <Michal.Kalderon@cavium.com>
Ming Lei <ming.lei@redhat.com>
Murray McAllister <murray.mcallister@insomniasec.com>
Nadav Amit <namit@vmware.com>
Neal Cardwell <ncardwell@google.com>
Nick Desaulniers <ndesaulniers@google.com>
Nico Sneck <snecknico@gmail.com>
Nicolas Ferre <nicolas.ferre@microchip.com>
Oleg Nesterov <oleg@redhat.com>
Olli Salonen <olli.salonen@iki.fi>
Or Gerlitz <ogerlitz@mellanox.com>
Oscar Salvador <osalvador@suse.de>
Pablo Neira Ayuso <pablo@netfilter.org>
Paul Burton <paul.burton@mips.com>
Paul Menzel <pmenzel@molgen.mpg.de>
Peter Zijlstra (Intel) <peterz@infradead.org>
Peter Zijlstra <peterz@infradead.org>
Ping-Ke Shih <pkshih@realtek.com>
Prashanth Prakash <pprakash@codeaurora.org>
Qing Xia <xiaqing17@hisilicon.com>
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Randy Dunlap <rdunlap@infradead.org>
Renato Westphal <renato@opensourcerouting.org>
Richard Weinberger <richard@nod.at>
Sabrina Dubroca <sd@queasysnail.net>
Saeed Mahameed <saeedm@mellanox.com>
Santosh Shilimkar <santosh.shilimkar@oracle.com>
Scott Bauer <scott.bauer@intel.com>
Sean Young <sean@mess.org>
Sedat Dilek <sedat.dilek@gmail.com>
Serge Semin <fancer.lancer@gmail.com>
Shay Agroskin <shayag@mellanox.com>
Shivam Kakkar <shivam543@gmail.com> # 8723BE on 4.18-rc1
Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
Stefan Agner <stefan@agner.ch>
Stefan Haberland <sth@linux.vnet.ibm.com>
Stefan Wahren <stefan.wahren@i2se.com>
Stephan Mueller <smueller@chronox.de>
Stephen Hemminger <sthemmin@microsoft.com>
Steve Wise <swise@opengridcomputing.com>
Steven Rostedt (VMware) <rostedt@goodmis.org>
Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Takashi Iwai <tiwai@suse.de>
Tejun Heo <tj@kernel.org>
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Theodore Ts'o <tytso@mit.edu>
Thierry Reding <treding@nvidia.com>
Thomas Gleixner <tglx@linutronix.de>
Tomas Bortoli <tomasbortoli@gmail.com>
Ulf Hansson <ulf.hansson@linaro.org>
Vlastimil Babka <vbabka@suse.cz>
Will Deacon <will.deacon@arm.com>
Willem de Bruijn <willemb@google.com>
Wolfram Sang <wsa@the-dreams.de>
x00270170 <xiaqing17@hisilicon.com>
Xin Long <lucien.xin@gmail.com>
Yandong Zhao <yandong77520@gmail.com>
Yuchung Cheng <ycheng@google.com>
jobs:
build-amd64-xsm pass
build-arm64-xsm pass
build-i386-xsm pass
build-amd64 pass
build-arm64 pass
build-armhf pass
build-i386 pass
build-amd64-libvirt pass
build-arm64-libvirt pass
build-armhf-libvirt pass
build-i386-libvirt pass
build-amd64-pvops pass
build-arm64-pvops pass
build-armhf-pvops pass
build-i386-pvops pass
build-amd64-rumprun pass
build-i386-rumprun pass
test-amd64-amd64-xl pass
test-arm64-arm64-xl pass
test-armhf-armhf-xl pass
test-amd64-i386-xl fail
test-amd64-amd64-xl-qemut-debianhvm-amd64-xsm pass
test-amd64-i386-xl-qemut-debianhvm-amd64-xsm pass
test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm pass
test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsm pass
test-amd64-amd64-xl-qemuu-debianhvm-amd64-xsm fail
test-amd64-i386-xl-qemuu-debianhvm-amd64-xsm pass
test-amd64-amd64-xl-qemut-stubdom-debianhvm-amd64-xsm pass
test-amd64-i386-xl-qemut-stubdom-debianhvm-amd64-xsm pass
test-amd64-amd64-libvirt-xsm pass
test-arm64-arm64-libvirt-xsm pass
test-amd64-i386-libvirt-xsm pass
test-amd64-amd64-xl-xsm pass
test-arm64-arm64-xl-xsm pass
test-amd64-i386-xl-xsm pass
test-amd64-amd64-qemuu-nested-amd fail
test-amd64-amd64-xl-pvhv2-amd fail
test-amd64-i386-qemut-rhel6hvm-amd fail
test-amd64-i386-qemuu-rhel6hvm-amd pass
test-amd64-amd64-xl-qemut-debianhvm-amd64 pass
test-amd64-i386-xl-qemut-debianhvm-amd64 pass
test-amd64-amd64-xl-qemuu-debianhvm-amd64 pass
test-amd64-i386-xl-qemuu-debianhvm-amd64 pass
test-amd64-i386-freebsd10-amd64 pass
test-amd64-amd64-xl-qemuu-ovmf-amd64 pass
test-amd64-i386-xl-qemuu-ovmf-amd64 pass
test-amd64-amd64-rumprun-amd64 pass
test-amd64-amd64-xl-qemut-win7-amd64 fail
test-amd64-i386-xl-qemut-win7-amd64 fail
test-amd64-amd64-xl-qemuu-win7-amd64 fail
test-amd64-i386-xl-qemuu-win7-amd64 fail
test-amd64-amd64-xl-qemut-ws16-amd64 fail
test-amd64-i386-xl-qemut-ws16-amd64 fail
test-amd64-amd64-xl-qemuu-ws16-amd64 fail
test-amd64-i386-xl-qemuu-ws16-amd64 fail
test-armhf-armhf-xl-arndale pass
test-amd64-amd64-xl-credit2 pass
test-arm64-arm64-xl-credit2 pass
test-armhf-armhf-xl-credit2 broken
test-armhf-armhf-xl-cubietruck pass
test-amd64-amd64-xl-qemuu-dmrestrict-amd64-dmrestrict fail
test-amd64-i386-xl-qemuu-dmrestrict-amd64-dmrestrict fail
test-amd64-amd64-examine pass
test-arm64-arm64-examine pass
test-armhf-armhf-examine pass
test-amd64-i386-examine pass
test-amd64-i386-freebsd10-i386 pass
test-amd64-i386-rumprun-i386 pass
test-amd64-amd64-xl-qemut-win10-i386 fail
test-amd64-i386-xl-qemut-win10-i386 fail
test-amd64-amd64-xl-qemuu-win10-i386 fail
test-amd64-i386-xl-qemuu-win10-i386 fail
test-amd64-amd64-qemuu-nested-intel pass
test-amd64-amd64-xl-pvhv2-intel pass
test-amd64-i386-qemut-rhel6hvm-intel pass
test-amd64-i386-qemuu-rhel6hvm-intel pass
test-amd64-amd64-libvirt pass
test-armhf-armhf-libvirt pass
test-amd64-i386-libvirt pass
test-amd64-amd64-xl-multivcpu pass
test-armhf-armhf-xl-multivcpu pass
test-amd64-amd64-pair pass
test-amd64-i386-pair pass
test-amd64-amd64-libvirt-pair pass
test-amd64-i386-libvirt-pair pass
test-amd64-amd64-amd64-pvgrub pass
test-amd64-amd64-i386-pvgrub pass
test-amd64-amd64-xl-pvshim fail
test-amd64-i386-xl-pvshim fail
test-amd64-amd64-pygrub pass
test-amd64-amd64-xl-qcow2 pass
test-armhf-armhf-libvirt-raw pass
test-amd64-i386-xl-raw pass
test-amd64-amd64-xl-rtds pass
test-armhf-armhf-xl-rtds pass
test-amd64-amd64-xl-qemuu-debianhvm-amd64-shadow fail
test-amd64-i386-xl-qemuu-debianhvm-amd64-shadow pass
test-amd64-amd64-xl-shadow pass
test-amd64-i386-xl-shadow pass
test-amd64-amd64-libvirt-vhd pass
test-armhf-armhf-xl-vhd pass
------------------------------------------------------------
sg-report-flight on osstest.test-lab.xenproject.org
logs: /home/logs/logs
images: /home/logs/images
Logs, config files, etc. are available at
http://logs.test-lab.xenproject.org/osstest/logs
Explanation of these reports, and of osstest in general, is at
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README.email;hb=master
http://xenbits.xen.org/gitweb/?p=osstest.git;a=blob;f=README;hb=master
Test harness code can be found at
http://xenbits.xen.org/gitweb?p=osstest.git;a=summary
broken-job test-armhf-armhf-xl-credit2 broken
broken-step test-armhf-armhf-xl-credit2 host-install(4)
Not pushing.
(No revision log; it would be 4657 lines long.)
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* Re: [PATCH v5 net-next 0/3] rds: IPv6 support
From: David Miller @ 2018-07-24 4:06 UTC (permalink / raw)
To: ka-cheong.poon; +Cc: netdev, santosh.shilimkar, rds-devel, sowmini.varadhan
In-Reply-To: <cover.1532404047.git.ka-cheong.poon@oracle.com>
Hello,
Since you have not fundamentally changed the code, just made
a build failure fix, would you please retain the ACKs that the
previous version received?
I either have to apply this as-is without the ACKs, or wait and
see if that person does the ACKs again for you.
Thank you.
^ permalink raw reply
* [PATCH] xfsprogs: remove generated scrub files under clean target
From: Eric Sandeen @ 2018-07-24 4:06 UTC (permalink / raw)
To: linux-xfs
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
diff --git a/scrub/Makefile b/scrub/Makefile
index d9ab148..acebecc 100644
--- a/scrub/Makefile
+++ b/scrub/Makefile
@@ -97,6 +97,8 @@ ifeq ($(HAVE_HDIO_GETGEO),yes)
LCFLAGS += -DHAVE_HDIO_GETGEO
endif
+LDIRT = $(XFS_SCRUB_ALL_PROG) *.service *.cron
+
default: depend $(LTCOMMAND) $(XFS_SCRUB_ALL_PROG) $(OPTIONAL_TARGETS)
xfs_scrub_all: xfs_scrub_all.in
^ permalink raw reply related
* [U-Boot] [PATCH 2/3] rockchip: add support for veyron-speedy (ASUS Chromebook C201)
From: Marty E. Plummer @ 2018-07-24 5:12 UTC (permalink / raw)
To: u-boot
In-Reply-To: <5B7BE192-291F-48F6-9247-D9BC37B4AFE6@theobroma-systems.com>
On Fri, Jul 13, 2018 at 12:31:49PM +0200, Dr. Philipp Tomsich wrote:
>
> > On 7 May 2018, at 02:20, Marty E. Plummer <hanetzer@startmail.com> wrote:
> >
> > On Mon, May 07, 2018 at 12:12:54AM +0200, klaus.goger at theobroma-systems.com <mailto:klaus.goger@theobroma-systems.com> wrote:
> >>
> >>> On 06.05.2018, at 16:25, Marty E. Plummer <hanetzer@startmail.com> wrote:
> >>>
> >>> This adds support for the ASUS C201, a RK3288-based clamshell
> >>> device. The device tree comes from linus's linux tree at
> >>> 87ef12027b9b1dd0e0b12cf311fbcb19f9d92539. The SDRAM parameters
> >>> are for 4GB Samsung LPDDR3, decoded from coreboot's
> >>> src/mainboard/google/veyron/sdram_inf/sdram-lpddr3-samsung-4GB.inc
> >>>
> >>> Signed-off-by: Marty E. Plummer <hanetzer@startmail.com>
> >>> ---
> >>> arch/arm/dts/Makefile | 1 +
> >>> arch/arm/dts/rk3288-veyron-speedy.dts | 189 ++++++++++++++++++++++
> >>> arch/arm/mach-rockchip/rk3288-board-spl.c | 3 +-
> >>> arch/arm/mach-rockchip/rk3288/Kconfig | 11 ++
> >>> board/google/veyron/Kconfig | 16 ++
> >>> configs/chromebook_speedy_defconfig | 96 +++++++++++
> >>> 6 files changed, 315 insertions(+), 1 deletion(-)
> >>> create mode 100644 arch/arm/dts/rk3288-veyron-speedy.dts
> >>> create mode 100644 configs/chromebook_speedy_defconfig
> >>>
> >>> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> >>> index ac7667b1e8..ee04d9bedd 100644
> >>> --- a/arch/arm/dts/Makefile
> >>> +++ b/arch/arm/dts/Makefile
> >>> @@ -42,6 +42,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
> >>> rk3288-veyron-jerry.dtb \
> >>> rk3288-veyron-mickey.dtb \
> >>> rk3288-veyron-minnie.dtb \
> >>> + rk3288-veyron-speedy.dtb \
> >>> rk3288-vyasa.dtb \
> >>> rk3328-evb.dtb \
> >>> rk3368-lion.dtb \
> >>> diff --git a/arch/arm/dts/rk3288-veyron-speedy.dts b/arch/arm/dts/rk3288-veyron-speedy.dts
> >>> new file mode 100644
> >>> index 0000000000..d5383cef0d
> >>> --- /dev/null
> >>> +++ b/arch/arm/dts/rk3288-veyron-speedy.dts
> >>
> >> This file looks quite different then the one I see on kernel.org with that revision id. So you are sure you
> >> imported that one?
> > Dafuq... it seems I borked something up in doing the patch juggling to
> > turn my single-commit mess of a patch (you know, the 'get the thing to
> > work branch') into a good patch series I messed up on this one.
> >>
> >>> @@ -0,0 +1,189 @@
> >>> +/*
> >>> + * Google Veyron Speedy Rev 1+ board device tree source
> >>> + *
> >>> + * Copyright 2015 Google, Inc
> >>> + *
> >>> + * SPDX-License-Identifier: GPL-2.0
> >>
> >> This file is dual licensed upstream, keep it that way.
> >> The comment will claim it's a X11 license but the license text below
> >> is actually MIT so you may want to use the MIT SPDX tag for that.
> >>
> > Yeah, I was listening in on the convo on irc. So, even though it 'says'
> > its GPL/X11, the actual license text is MIT, so I should use that tag?
> > Its not my code, obviously, so I have no dog in that race anyways.
> >>> + */
> >>> +
> >>> +/dts-v1/;
> >>> +#include "rk3288-veyron-chromebook.dtsi"
> >>> +#include "cros-ec-sbs.dtsi"
> >>> +
> >>> +/ {
> >>> + model = "Google Speedy";
> >>> + compatible = "google,veyron-speedy-rev9", "google,veyron-speedy-rev8",
> >>> + "google,veyron-speedy-rev7", "google,veyron-speedy-rev6",
> >>> + "google,veyron-speedy-rev5", "google,veyron-speedy-rev4",
> >>> + "google,veyron-speedy-rev3", "google,veyron-speedy-rev2",
> >>> + "google,veyron-speedy", "google,veyron", "rockchip,rk3288";
> >>> +
> >>> + chosen {
> >>> + stdout-path = &uart2;
> >>> + };
> >>> +
> >>> + panel_regulator: panel-regulator {
> >>> + compatible = "regulator-fixed";
> >>> + enable-active-high;
> >>> + gpio = <&gpio7 RK_PB6 GPIO_ACTIVE_HIGH>;
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&lcd_enable_h>;
> >>> + regulator-name = "panel_regulator";
> >>> + startup-delay-us = <100000>;
> >>> + vin-supply = <&vcc33_sys>;
> >>> + };
> >>> +
> >>> + vcc18_lcd: vcc18-lcd {
> >>> + compatible = "regulator-fixed";
> >>> + enable-active-high;
> >>> + gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_HIGH>;
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&avdd_1v8_disp_en>;
> >>> + regulator-name = "vcc18_lcd";
> >>> + regulator-always-on;
> >>> + regulator-boot-on;
> >>> + vin-supply = <&vcc18_wl>;
> >>> + };
> >>> +
> >>> + backlight_regulator: backlight-regulator {
> >>> + compatible = "regulator-fixed";
> >>> + enable-active-high;
> >>> + gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&bl_pwr_en>;
> >>> + regulator-name = "backlight_regulator";
> >>> + vin-supply = <&vcc33_sys>;
> >>> + startup-delay-us = <15000>;
> >>> + };
> >>> +};
> >>> +
> >>> +&dmc {
> >>> + rockchip,pctl-timing = <0x215 0xc8 0x0 0x35 0x26 0x2 0x70 0x2000d
> >>> + 0x6 0x0 0x8 0x4 0x17 0x24 0xd 0x6
> >>> + 0x4 0x8 0x4 0x76 0x4 0x0 0x30 0x0
> >>> + 0x1 0x2 0x2 0x4 0x0 0x0 0xc0 0x4
> >>> + 0x8 0x1f4>;
> >>> + rockchip,phy-timing = <0x48d7dd93 0x187008d8 0x121076
> >>> + 0x0 0xc3 0x6 0x1>;
> >>> + rockchip,sdram-params = <0x20D266A4 0x5B6 6 533000000 6 13 0>;
> >>> +};
> >>
> >> Not sure if this should go into a separate dtsi. One of the maintainer will have
> >> a preferred way I think, so lets see what they will add.
> >>
> > Yeah, that is possible. However, here I just followed the example of
> > rk3288-veyron-jerry.dtsi, which I (perhaps wrongly) assume can come in
> > other memory size variants.
>
> Having a “-u-boot.dtsi” is the current practice (counting 85 such files as of today).
> We should follow this model here as well for any new devices we add.
>
Fair. So what should go into the -u-boot.dtsi file? everything not
standard to the imported dts/dtsi from linux?
> >>> +&gpio_keys {
> >>> + power {
> >>> + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
> >>> + };
> >>> +};
> >>> +
> >>> +&backlight {
> >>> + power-supply = <&backlight_regulator>;
> >>> +};
> >>> +
> >>> +&panel {
> >>> + power-supply = <&panel_regulator>;
> >>> +};
> >>> +
> >>> +&rk808 {
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&pmic_int_l>;
> >>> +};
> >>> +
> >>> +&sdmmc {
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio
> >>> + &sdmmc_bus4>;
> >>> + disable-wp;
> >>> +};
> >>> +
> >>> +&vcc_5v {
> >>> + enable-active-high;
> >>> + gpio = <&gpio7 RK_PC5 GPIO_ACTIVE_HIGH>;
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&drv_5v>;
> >>> +};
> >>> +
> >>> +&vcc50_hdmi {
> >>> + enable-active-high;
> >>> + gpio = <&gpio5 RK_PC3 GPIO_ACTIVE_HIGH>;
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&vcc50_hdmi_en>;
> >>> +};
> >>> +
> >>> +&edp {
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&edp_hpd>;
> >>> +};
> >>> +
> >>> +&pinctrl {
> >>> + backlight {
> >>> + bl_pwr_en: bl_pwr_en {
> >>> + rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
> >>> + };
> >>> + };
> >>> +
> >>> + buck-5v {
> >>> + drv_5v: drv-5v {
> >>> + rockchip,pins = <7 21 RK_FUNC_GPIO &pcfg_pull_none>;
> >>> + };
> >>> + };
> >>> +
> >>> + edp {
> >>> + edp_hpd: edp_hpd {
> >>> + rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_down>;
> >>> + };
> >>> + };
> >>> +
> >>> + emmc {
> >>> + /* Make sure eMMC is not in reset */
> >>> + emmc_deassert_reset: emmc-deassert-reset {
> >>> + rockchip,pins = <2 9 RK_FUNC_GPIO &pcfg_pull_none>;
> >>> + };
> >>> + };
> >>> +
> >>> + hdmi {
> >>> + vcc50_hdmi_en: vcc50-hdmi-en {
> >>> + rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>;
> >>> + };
> >>> + };
> >>> +
> >>> + lcd {
> >>> + lcd_enable_h: lcd-en {
> >>> + rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_pull_none>;
> >>> + };
> >>> +
> >>> + avdd_1v8_disp_en: avdd-1v8-disp-en {
> >>> + rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
> >>> + };
> >>> + };
> >>> +
> >>> + pmic {
> >>> + dvs_1: dvs-1 {
> >>> + rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_down>;
> >>> + };
> >>> +
> >>> + dvs_2: dvs-2 {
> >>> + rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
> >>> + };
> >>> + };
> >>> +};
> >>> +
> >>> +&i2c4 {
> >>> + status = "okay";
> >>> +
> >>> + pinctrl-names = "default";
> >>> + pinctrl-0 = <&i2c4_xfer>;
> >>> +
> >>> + trackpad at 15 {
> >>> + compatible = "elan,i2c_touchpad";
> >>> + interrupt-parent = <&gpio7>;
> >>> + interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
> >>> + /*
> >>> + * Remove the inherited pinctrl settings to avoid clashing
> >>> + * with bus-wide ones.
> >>> + */
> >>> + /delete-property/pinctrl-names;
> >>> + /delete-property/pinctrl-0;
> >>> + reg = <0x15>;
> >>> + vcc-supply = <&vcc33_io>;
> >>> + wakeup-source;
> >>> + };
> >>> +};
> >>> diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
> >>> index f3ea624277..9ae4802647 100644
> >>> --- a/arch/arm/mach-rockchip/rk3288-board-spl.c
> >>> +++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
> >>> @@ -72,7 +72,8 @@ u32 spl_boot_device(void)
> >>> fallback:
> >>> #elif defined(CONFIG_TARGET_CHROMEBOOK_JERRY) || \
> >>> defined(CONFIG_TARGET_CHROMEBIT_MICKEY) || \
> >>> - defined(CONFIG_TARGET_CHROMEBOOK_MINNIE)
> >>> + defined(CONFIG_TARGET_CHROMEBOOK_MINNIE) || \
> >>> + defined(CONFIG_TARGET_CHROMEBOOK_SPEEDY)
> >>> return BOOT_DEVICE_SPI;
> >>> #endif
> >>> return BOOT_DEVICE_MMC1;
> >>> diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
> >>> index 6beb26fd7a..8d1d37895d 100644
> >>> --- a/arch/arm/mach-rockchip/rk3288/Kconfig
> >>> +++ b/arch/arm/mach-rockchip/rk3288/Kconfig
> >>> @@ -30,6 +30,17 @@ config TARGET_CHROMEBOOK_MINNIE
> >>> functions. It includes 2 or 4GB of SDRAM and 16 or 32GB of
> >>> internal MMC. The product name is ASUS Chromebook Flip.
> >>>
> >>> +config TARGET_CHROMEBOOK_SPEEDY
> >>> + bool "Google/Rockchip Veyron-Speedy Chromebook"
> >>> + select BOARD_LATE_INIT
> >>> + help
> >>> + Speedy is a RK3288-based clamshell device with 2 USB 2.0 ports,
> >>> + micro HDMI, an 11.6 inch display, micro-SD card,
> >>> + HD camera, touchpad, wifi and Bluetooth. It includes a Chrome OS
> >>> + EC (Cortex-M3) to provide access to the keyboard and battery
> >>> + functions. It includes 2 or 4GB of SDRAM and 16GB of internal MMC.
> >>> + The product name is Asus Chromebook C201PA.
> >>> +
> >>> config TARGET_EVB_RK3288
> >>> bool "Evb-RK3288"
> >>> select BOARD_LATE_INIT
> >>> diff --git a/board/google/veyron/Kconfig b/board/google/veyron/Kconfig
> >>> index 770e9aad28..7f55d78dac 100644
> >>> --- a/board/google/veyron/Kconfig
> >>> +++ b/board/google/veyron/Kconfig
> >>> @@ -45,3 +45,19 @@ config BOARD_SPECIFIC_OPTIONS # dummy
> >>> def_bool y
> >>>
> >>> endif
> >>> +
> >>> +if TARGET_CHROMEBOOK_SPEEDY
> >>> +
> >>> +config SYS_BOARD
> >>> + default "veyron"
> >>> +
> >>> +config SYS_VENDOR
> >>> + default "google"
> >>> +
> >>> +config SYS_CONFIG_NAME
> >>> + default "veyron"
> >>> +
> >>> +config BOARD_SPECIFIC_OPTIONS # dummy
> >>> + def_bool y
> >>> +
> >>> +endif
> >>> diff --git a/configs/chromebook_speedy_defconfig b/configs/chromebook_speedy_defconfig
> >>> new file mode 100644
> >>> index 0000000000..8789b56f37
> >>> --- /dev/null
> >>> +++ b/configs/chromebook_speedy_defconfig
> >>> @@ -0,0 +1,96 @@
> >>> +CONFIG_ARM=y
> >>> +CONFIG_ARCH_ROCKCHIP=y
> >>> +CONFIG_SYS_TEXT_BASE=0x00100000
> >>> +CONFIG_SYS_MALLOC_F_LEN=0x2000
> >>> +CONFIG_ROCKCHIP_RK3288=y
> >>> +# CONFIG_SPL_MMC_SUPPORT is not set
> >>> +CONFIG_TARGET_CHROMEBOOK_SPEEDY=y
> >>> +CONFIG_SPL_SPI_FLASH_SUPPORT=y
> >>> +CONFIG_SPL_SPI_SUPPORT=y
> >>> +CONFIG_SPL_STACK_R_ADDR=0x80000
> >>> +CONFIG_DEFAULT_DEVICE_TREE="rk3288-veyron-speedy"
> >>> +CONFIG_DEBUG_UART=y
> >>> +# CONFIG_ANDROID_BOOT_IMAGE is not set
> >>> +CONFIG_SILENT_CONSOLE=y
> >>> +# CONFIG_DISPLAY_CPUINFO is not set
> >>> +CONFIG_DISPLAY_BOARDINFO_LATE=y
> >>> +CONFIG_BOARD_EARLY_INIT_F=y
> >>> +CONFIG_SPL_STACK_R=y
> >>> +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
> >>> +CONFIG_SPL_SPI_LOAD=y
> >>> +CONFIG_FASTBOOT_FLASH=y
> >>> +CONFIG_FASTBOOT_FLASH_MMC_DEV=0
> >>> +CONFIG_CMD_GPIO=y
> >>> +CONFIG_CMD_GPT=y
> >>> +CONFIG_CMD_I2C=y
> >>> +CONFIG_CMD_MMC=y
> >>> +CONFIG_CMD_SF=y
> >>> +CONFIG_CMD_SF_TEST=y
> >>> +CONFIG_CMD_SPI=y
> >>> +CONFIG_CMD_USB=y
> >>> +# CONFIG_CMD_SETEXPR is not set
> >>> +CONFIG_CMD_CACHE=y
> >>> +CONFIG_CMD_TIME=y
> >>> +CONFIG_CMD_PMIC=y
> >>> +CONFIG_CMD_REGULATOR=y
> >>> +# CONFIG_SPL_DOS_PARTITION is not set
> >>> +# CONFIG_SPL_EFI_PARTITION is not set
> >>> +CONFIG_SPL_PARTITION_UUIDS=y
> >>> +CONFIG_SPL_OF_CONTROL=y
> >>> +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
> >>> +CONFIG_SPL_OF_PLATDATA=y
> >>> +CONFIG_REGMAP=y
> >>> +CONFIG_SPL_REGMAP=y
> >>> +CONFIG_SYSCON=y
> >>> +CONFIG_SPL_SYSCON=y
> >>> +# CONFIG_SPL_SIMPLE_BUS is not set
> >>> +CONFIG_CLK=y
> >>> +CONFIG_SPL_CLK=y
> >>> +CONFIG_ROCKCHIP_GPIO=y
> >>> +CONFIG_I2C_CROS_EC_TUNNEL=y
> >>> +CONFIG_SYS_I2C_ROCKCHIP=y
> >>> +CONFIG_I2C_MUX=y
> >>> +CONFIG_DM_KEYBOARD=y
> >>> +CONFIG_CROS_EC_KEYB=y
> >>> +CONFIG_CROS_EC=y
> >>> +CONFIG_CROS_EC_SPI=y
> >>> +CONFIG_PWRSEQ=y
> >>> +CONFIG_MMC_DW=y
> >>> +CONFIG_MMC_DW_ROCKCHIP=y
> >>> +CONFIG_PINCTRL=y
> >>> +CONFIG_SPL_PINCTRL=y
> >>> +# CONFIG_SPL_PINCTRL_FULL is not set
> >>> +CONFIG_PINCTRL_ROCKCHIP_RK3288=y
> >>> +CONFIG_DM_PMIC=y
> >>> +# CONFIG_SPL_PMIC_CHILDREN is not set
> >>> +CONFIG_PMIC_RK8XX=y
> >>> +CONFIG_DM_REGULATOR_FIXED=y
> >>> +CONFIG_REGULATOR_RK8XX=y
> >>> +CONFIG_PWM_ROCKCHIP=y
> >>> +CONFIG_RAM=y
> >>> +CONFIG_SPL_RAM=y
> >>> +CONFIG_DEBUG_UART_BASE=0xff690000
> >>> +CONFIG_DEBUG_UART_CLOCK=24000000
> >>> +CONFIG_DEBUG_UART_SHIFT=2
> >>> +CONFIG_SYS_NS16550=y
> >>> +CONFIG_ROCKCHIP_SERIAL=y
> >>> +CONFIG_ROCKCHIP_SPI=y
> >>> +CONFIG_SYSRESET=y
> >>> +CONFIG_USB=y
> >>> +CONFIG_ROCKCHIP_USB2_PHY=y
> >>> +CONFIG_USB_STORAGE=y
> >>> +CONFIG_USB_GADGET=y
> >>> +CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
> >>> +CONFIG_USB_GADGET_VENDOR_NUM=0x2207
> >>> +CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
> >>> +CONFIG_USB_GADGET_DWC2_OTG=y
> >>> +CONFIG_USB_FUNCTION_MASS_STORAGE=y
> >>> +CONFIG_DM_VIDEO=y
> >>> +CONFIG_DISPLAY=y
> >>> +CONFIG_VIDEO_ROCKCHIP=y
> >>> +CONFIG_DISPLAY_ROCKCHIP_EDP=y
> >>> +CONFIG_DISPLAY_ROCKCHIP_HDMI=y
> >>> +CONFIG_USE_TINY_PRINTF=y
> >>> +CONFIG_CMD_DHRYSTONE=y
> >>> +CONFIG_ERRNO_STR=y
> >>> +# CONFIG_SPL_OF_LIBFDT is not set
> >>> --
> >>> 2.17.0
> >>>
> >>> _______________________________________________
> >>> U-Boot mailing list
> >>> U-Boot at lists.denx.de
> >>> https://lists.denx.de/listinfo/u-boot
> >>
> > _______________________________________________
> > U-Boot mailing list
> > U-Boot at lists.denx.de
> > https://lists.denx.de/listinfo/u-boot
>
^ permalink raw reply
* Re: KASAN: use-after-free Read in link_path_walk
From: DaeRyong Jeong @ 2018-07-24 4:08 UTC (permalink / raw)
To: viro; +Cc: linux-fsdevel, LKML, Byoungyoung Lee, Kyungtae Kim, bammanag
In-Reply-To: <20180724034542.GA19283@dragonet>
I think that below two crashes are also related to the same race issue.
KASAN: use-after-free Read in nd_jump_root, found in v4.17-rc1
KASAN: use-after-free in set_root, found in v4.18-rc3
==================================================================
BUG: KASAN: use-after-free in nd_jump_root+0x69/0x160 fs/namei.c:852
Read of size 8 at addr ffff8801eb677e58 by task syz-executor0/20521
CPU: 0 PID: 20521 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x166/0x21c lib/dump_stack.c:113
print_address_description+0x73/0x250 mm/kasan/report.c:256
kasan_report_error mm/kasan/report.c:354 [inline]
kasan_report+0x23f/0x360 mm/kasan/report.c:412
check_memory_region_inline mm/kasan/kasan.c:260 [inline]
__asan_load8+0x54/0x90 mm/kasan/kasan.c:699
nd_jump_root+0x69/0x160 fs/namei.c:852
path_init+0x9ca/0x1190 fs/namei.c:2165
path_openat+0x140/0x2040 fs/namei.c:3495
do_filp_open+0x175/0x230 fs/namei.c:3535
do_sys_open+0x3c7/0x4a0 fs/open.c:1093
__do_sys_openat fs/open.c:1120 [inline]
__se_sys_openat fs/open.c:1114 [inline]
__x64_sys_openat+0x59/0x70 fs/open.c:1114
do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x456419
RSP: 002b:00007fb317cd2b28 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 000000000072bee0 RCX: 0000000000456419
RDX: 0000000000000101 RSI: 00000000200001c0 RDI: ffffffffffffff9c
RBP: 0000000000000497 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007fb317cd36d4
R13: 00000000ffffffff R14: 00000000006fbec8 R15: 0000000000000000
Allocated by task 20521:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553
kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:490
kmem_cache_alloc+0x12e/0x760 mm/slab.c:3554
__d_alloc+0xc0/0x6e0 fs/dcache.c:1638
d_alloc_anon fs/dcache.c:1742 [inline]
d_make_root+0x2d/0x70 fs/dcache.c:1934
devpts_fill_super+0x23b/0x500 fs/devpts/inode.c:482
mount_nodev+0x59/0xd0 fs/super.c:1211
devpts_mount+0x2c/0x40 fs/devpts/inode.c:509
mount_fs+0x50/0x200 fs/super.c:1268
vfs_kern_mount.part.26+0xbc/0x2c0 fs/namespace.c:1037
vfs_kern_mount fs/namespace.c:2514 [inline]
do_new_mount fs/namespace.c:2517 [inline]
do_mount+0xb82/0x1bb0 fs/namespace.c:2847
ksys_mount+0xab/0x120 fs/namespace.c:3063
__do_sys_mount fs/namespace.c:3077 [inline]
__se_sys_mount fs/namespace.c:3074 [inline]
__x64_sys_mount+0x67/0x80 fs/namespace.c:3074
do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Freed by task 20522:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
__kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:521
kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
__cache_free mm/slab.c:3498 [inline]
kmem_cache_free+0x83/0x2a0 mm/slab.c:3756
__d_free fs/dcache.c:257 [inline]
dentry_free+0x8c/0xe0 fs/dcache.c:347
__dentry_kill+0x3d6/0x440 fs/dcache.c:582
dentry_kill+0x8f/0x320 fs/dcache.c:686
dput.part.22+0x430/0x4e0 fs/dcache.c:850
dput fs/dcache.c:830 [inline]
do_one_tree+0x43/0x50 fs/dcache.c:1523
shrink_dcache_for_umount+0xa5/0x1c0 fs/dcache.c:1537
generic_shutdown_super+0xb0/0x330 fs/super.c:425
kill_anon_super fs/super.c:1037 [inline]
kill_litter_super+0x48/0x60 fs/super.c:1047
devpts_kill_sb+0x49/0x50 fs/devpts/inode.c:519
deactivate_locked_super+0x71/0xb0 fs/super.c:313
deactivate_super+0x10f/0x150 fs/super.c:344
cleanup_mnt+0x6b/0xc0 fs/namespace.c:1173
__cleanup_mnt+0x16/0x20 fs/namespace.c:1180
task_work_run+0x152/0x1b0 kernel/task_work.c:113
tracehook_notify_resume include/linux/tracehook.h:191 [inline]
exit_to_usermode_loop+0x262/0x270 arch/x86/entry/common.c:166
prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline]
syscall_return_slowpath arch/x86/entry/common.c:265 [inline]
do_syscall_64+0x473/0x4a0 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff8801eb677e00
which belongs to the cache dentry(17:syz0) of size 288
The buggy address is located 88 bytes inside of
288-byte region [ffff8801eb677e00, ffff8801eb677f20)
The buggy address belongs to the page:
page:ffffea0007ad9dc0 count:1 mapcount:0 mapping:ffff8801eb677040 index:0x0
flags: 0x2fffc0000000100(slab)
raw: 02fffc0000000100 ffff8801eb677040 0000000000000000 000000010000000b
raw: ffffea0007b9d2a0 ffffea0007b9ed20 ffff8801ef225300 ffff8801ed0249c0
page dumped because: kasan: bad access detected
page->mem_cgroup:ffff8801ed0249c0
Memory state around the buggy address:
ffff8801eb677d00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8801eb677d80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff8801eb677e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff8801eb677e80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8801eb677f00: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================
==================================================================
BUG: KASAN: use-after-free in __read_once_size
include/linux/compiler.h:188 [inline]
BUG: KASAN: use-after-free in __read_seqcount_begin
include/linux/seqlock.h:113 [inline]
BUG: KASAN: use-after-free in set_root+0x252/0x3f0 fs/namei.c:820
Read of size 4 at addr ffff88019e5d4b88 by task syz-executor0/30297
CPU: 1 PID: 30297 Comm: syz-executor0 Not tainted 4.18.0-rc3 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x16e/0x22c lib/dump_stack.c:113
print_address_description+0x73/0x250 mm/kasan/report.c:256
kasan_report_error mm/kasan/report.c:354 [inline]
kasan_report+0x259/0x380 mm/kasan/report.c:412
check_memory_region_inline mm/kasan/kasan.c:260 [inline]
__asan_load4+0x78/0x80 mm/kasan/kasan.c:698
__read_once_size include/linux/compiler.h:188 [inline]
__read_seqcount_begin include/linux/seqlock.h:113 [inline]
set_root+0x252/0x3f0 fs/namei.c:820
path_init+0x9dd/0x11b0 fs/namei.c:2164
path_openat+0x147/0x1fb0 fs/namei.c:3534
do_filp_open+0x181/0x250 fs/namei.c:3574
do_sys_open+0x3da/0x4b0 fs/open.c:1101
__do_sys_openat fs/open.c:1128 [inline]
__se_sys_openat fs/open.c:1122 [inline]
__x64_sys_openat+0x59/0x70 fs/open.c:1122
do_syscall_64+0x167/0x4b0 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x456469
Code: 1d ba fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48
89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d
01 f0 ff ff 0f 83 eb b9 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f5e06564b28 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 000000000072bfa0 RCX: 0000000000456469
RDX: 0000000000000080 RSI: 0000000020000140 RDI: ffffffffffffff9c
RBP: 00000000000004e4 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f5e065656d4
R13: 00000000ffffffff R14: 00000000006fc600 R15: 0000000000000000
Allocated by task 30296:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553
kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:490
kmem_cache_alloc+0x12e/0x750 mm/slab.c:3554
__d_alloc+0xc2/0x720 fs/dcache.c:1616
d_alloc_anon fs/dcache.c:1720 [inline]
d_make_root+0x2d/0x70 fs/dcache.c:1934
devpts_fill_super+0x23b/0x500 fs/devpts/inode.c:482
mount_nodev+0x59/0xd0 fs/super.c:1220
devpts_mount+0x2c/0x40 fs/devpts/inode.c:509
mount_fs+0x50/0x200 fs/super.c:1277
vfs_kern_mount.part.26+0xc4/0x2d0 fs/namespace.c:1037
vfs_kern_mount fs/namespace.c:2515 [inline]
do_new_mount fs/namespace.c:2518 [inline]
do_mount+0xbd7/0x1c90 fs/namespace.c:2848
ksys_mount+0xab/0x120 fs/namespace.c:3064
__do_sys_mount fs/namespace.c:3078 [inline]
__se_sys_mount fs/namespace.c:3075 [inline]
__x64_sys_mount+0x67/0x80 fs/namespace.c:3075
do_syscall_64+0x167/0x4b0 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Freed by task 30296:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
__kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:521
kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
__cache_free mm/slab.c:3498 [inline]
kmem_cache_free+0x83/0x2a0 mm/slab.c:3756
__d_free fs/dcache.c:257 [inline]
dentry_free+0x8c/0xe0 fs/dcache.c:347
__dentry_kill+0x3fe/0x470 fs/dcache.c:582
dentry_kill+0x8f/0x320 fs/dcache.c:687
dput+0x450/0x4e0 fs/dcache.c:848
do_one_tree+0x37/0x40 fs/dcache.c:1531
shrink_dcache_for_umount+0xad/0x1d0 fs/dcache.c:1545
generic_shutdown_super+0xb8/0x340 fs/super.c:438
kill_anon_super fs/super.c:1046 [inline]
kill_litter_super+0x48/0x60 fs/super.c:1056
devpts_kill_sb+0x49/0x50 fs/devpts/inode.c:519
deactivate_locked_super+0x71/0xb0 fs/super.c:326
deactivate_super+0x11d/0x160 fs/super.c:357
cleanup_mnt+0x6b/0xc0 fs/namespace.c:1174
__cleanup_mnt+0x16/0x20 fs/namespace.c:1181
task_work_run+0x15a/0x1c0 kernel/task_work.c:113
tracehook_notify_resume include/linux/tracehook.h:192 [inline]
exit_to_usermode_loop+0x2a3/0x2b0 arch/x86/entry/common.c:166
prepare_exit_to_usermode arch/x86/entry/common.c:197 [inline]
syscall_return_slowpath arch/x86/entry/common.c:268 [inline]
do_syscall_64+0x485/0x4b0 arch/x86/entry/common.c:293
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff88019e5d4b80
which belongs to the cache dentry(17:syz0) of size 288
The buggy address is located 8 bytes inside of
288-byte region [ffff88019e5d4b80, ffff88019e5d4ca0)
The buggy address belongs to the page:
page:ffffea0006797500 count:1 mapcount:0 mapping:ffff8801ec05d7c0 index:0x0
flags: 0x2fffc0000000100(slab)
raw: 02fffc0000000100 ffffea0006796148 ffffea00067cd648 ffff8801ec05d7c0
raw: 0000000000000000 ffff88019e5d4080 000000010000000b ffff8801dc63e8c0
page dumped because: kasan: bad access detected
page->mem_cgroup:ffff8801dc63e8c0
Memory state around the buggy address:
ffff88019e5d4a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88019e5d4b00: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff88019e5d4b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff88019e5d4c00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88019e5d4c80: fb fb fb fb fc fc fc fc fc fc fc fc fb fb fb fb
==================================================================
On Tue, Jul 24, 2018 at 12:45 PM, Dae R. Jeong <threeearcat@gmail.com> wrote:
> Reporting the crash: KASAN: use-after-free Read in link_path_walk
>
> This crash has been found in v4.17-rc1 using RaceFuzzer (a modified
> version of Syzkaller), which we describe more at the end of this
> report. Our analysis shows that the race occurs when invoking two
> syscalls concurrently, open() and chroot().
>
> Diagnosis:
> We think that it is possible that link_path_walk() dereferences a
> freed pointer when cleanup_mnt() is executed between path_init() and
> link_path_walk().
>
> Since I'm not an expert on a file system and don't fully understand
> the crash, please see a executed program and a crash log below in
> case that my understanding is wrong.
>
>
> Executed Program:
> Thread0 Thread1
> mkdir("./file0")
> |--------------------------|
> | mount("./file0", "./file0", "devpts", 0x0, "")
> | |
> openat(AT_FDCWD, chroot("./file0")
> "/dev/vcs", 0x200, 0x0) umount("./file0", 0x2)
>
> openat(), chroot(), umount() syscalls are executed after mount() syscall.
> We think a race occurs between openat() and chroot() because RaceFuzzer
> executed openat() and chroot() concurrently.
>
>
> (Possible) Thread interleaving:
> CPU0 (path_openat) CPU1 (cleanup_mnt)
> ===== =====
> s = path_init(nd, flags);
> if (IS_ERR(s)) {
> put_filp(file);
> return ERR_CAST(s);
> }
>
> deactivate_super(mnt->mnt.mnt_sb);
>
> while (!(error = link_path_walk(s, nd)) &&
>
> // (in link_path_walk())
> struct dentry *parent = nd->path.dentry;
> nd->flags &= ~LOOKUP_JUMPED;
> if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { // UAF occured
>
>
> Crash log:
> ==================================================================
> BUG: KASAN: use-after-free in link_path_walk+0x46e/0xcd0 fs/namei.c:2061
> Read of size 4 at addr ffff8801cbe6cb80 by task syz-executor0/28699
>
> CPU: 0 PID: 28699 Comm: syz-executor0 Not tainted 4.17.0-rc1 #1
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
> Call Trace:
> __dump_stack lib/dump_stack.c:77 [inline]
> dump_stack+0x166/0x21c lib/dump_stack.c:113
> print_address_description+0x73/0x250 mm/kasan/report.c:256
> kasan_report_error mm/kasan/report.c:354 [inline]
> kasan_report+0x23f/0x360 mm/kasan/report.c:412
> check_memory_region_inline mm/kasan/kasan.c:260 [inline]
> __asan_load4+0x78/0x80 mm/kasan/kasan.c:698
> link_path_walk+0x46e/0xcd0 fs/namei.c:2061
> path_openat+0x23c/0x2040 fs/namei.c:3500
> do_filp_open+0x175/0x230 fs/namei.c:3535
> do_sys_open+0x3c7/0x4a0 fs/open.c:1093
> __do_sys_open fs/open.c:1111 [inline]
> __se_sys_open fs/open.c:1106 [inline]
> __x64_sys_open+0x4c/0x60 fs/open.c:1106
> do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
> RIP: 0033:0x410601
> RSP: 002b:00007f7345489660 EFLAGS: 00000293 ORIG_RAX: 0000000000000002
> RAX: ffffffffffffffda RBX: cccccccccccccccd RCX: 0000000000410601
> RDX: 0000000000000000 RSI: 0000000000010180 RDI: 00007f7345489710
> RBP: 00000000000006e1 R08: 236573756f6d2f74 R09: 0000000000000000
> R10: 00000000200004c0 R11: 0000000000000293 R12: 00007f734548a6d4
> R13: 00000000ffffffff R14: 00000000006ff5b8 R15: 0000000000000000
>
> Allocated by task 28699:
> save_stack+0x43/0xd0 mm/kasan/kasan.c:448
> set_track mm/kasan/kasan.c:460 [inline]
> kasan_kmalloc+0xae/0xe0 mm/kasan/kasan.c:553
> kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:490
> kmem_cache_alloc+0x12e/0x760 mm/slab.c:3554
> __d_alloc+0xc0/0x6e0 fs/dcache.c:1638
> d_alloc_anon fs/dcache.c:1742 [inline]
> d_make_root+0x2d/0x70 fs/dcache.c:1934
> devpts_fill_super+0x23b/0x500 fs/devpts/inode.c:482
> mount_nodev+0x59/0xd0 fs/super.c:1211
> devpts_mount+0x2c/0x40 fs/devpts/inode.c:509
> mount_fs+0x50/0x200 fs/super.c:1268
> vfs_kern_mount.part.26+0xbc/0x2c0 fs/namespace.c:1037
> vfs_kern_mount fs/namespace.c:2514 [inline]
> do_new_mount fs/namespace.c:2517 [inline]
> do_mount+0xb82/0x1bb0 fs/namespace.c:2847
> ksys_mount+0xab/0x120 fs/namespace.c:3063
> __do_sys_mount fs/namespace.c:3077 [inline]
> __se_sys_mount fs/namespace.c:3074 [inline]
> __x64_sys_mount+0x67/0x80 fs/namespace.c:3074
> do_syscall_64+0x15f/0x4a0 arch/x86/entry/common.c:287
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> Freed by task 28700:
> save_stack+0x43/0xd0 mm/kasan/kasan.c:448
> set_track mm/kasan/kasan.c:460 [inline]
> __kasan_slab_free+0x11a/0x170 mm/kasan/kasan.c:521
> kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
> __cache_free mm/slab.c:3498 [inline]
> kmem_cache_free+0x83/0x2a0 mm/slab.c:3756
> __d_free fs/dcache.c:257 [inline]
> dentry_free+0x8c/0xe0 fs/dcache.c:347
> __dentry_kill+0x3d6/0x440 fs/dcache.c:582
> dentry_kill+0x8f/0x320 fs/dcache.c:686
> dput.part.22+0x430/0x4e0 fs/dcache.c:850
> dput fs/dcache.c:830 [inline]
> do_one_tree+0x43/0x50 fs/dcache.c:1523
> shrink_dcache_for_umount+0xa5/0x1c0 fs/dcache.c:1537
> generic_shutdown_super+0xb0/0x330 fs/super.c:425
> kill_anon_super fs/super.c:1037 [inline]
> kill_litter_super+0x48/0x60 fs/super.c:1047
> devpts_kill_sb+0x49/0x50 fs/devpts/inode.c:519
> deactivate_locked_super+0x71/0xb0 fs/super.c:313
> deactivate_super+0x10f/0x150 fs/super.c:344
> cleanup_mnt+0x6b/0xc0 fs/namespace.c:1173
> __cleanup_mnt+0x16/0x20 fs/namespace.c:1180
> task_work_run+0x152/0x1b0 kernel/task_work.c:113
> tracehook_notify_resume include/linux/tracehook.h:191 [inline]
> exit_to_usermode_loop+0x262/0x270 arch/x86/entry/common.c:166
> prepare_exit_to_usermode arch/x86/entry/common.c:196 [inline]
> syscall_return_slowpath arch/x86/entry/common.c:265 [inline]
> do_syscall_64+0x473/0x4a0 arch/x86/entry/common.c:290
> entry_SYSCALL_64_after_hwframe+0x49/0xbe
>
> The buggy address belongs to the object at ffff8801cbe6cb80
> which belongs to the cache dentry(17:syz0) of size 288
> The buggy address is located 0 bytes inside of
> 288-byte region [ffff8801cbe6cb80, ffff8801cbe6cca0)
> The buggy address belongs to the page:
> page:ffffea00072f9b00 count:1 mapcount:0 mapping:ffff8801cbe6c080 index:0x0
> flags: 0x2fffc0000000100(slab)
> raw: 02fffc0000000100 ffff8801cbe6c080 0000000000000000 000000010000000b
> raw: ffffea00072f8ca0 ffffea00072f8da0 ffff8801dc812c80 ffff8801de41a740
> page dumped because: kasan: bad access detected
> page->mem_cgroup:ffff8801de41a740
>
> Memory state around the buggy address:
> ffff8801cbe6ca80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ffff8801cbe6cb00: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>>ffff8801cbe6cb80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ^
> ffff8801cbe6cc00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ffff8801cbe6cc80: fb fb fb fb fc fc fc fc fc fc fc fc fb fb fb fb
> ==================================================================
>
>
> = About RaceFuzzer
>
> RaceFuzzer is a customized version of Syzkaller, specifically tailored
> to find race condition bugs in the Linux kernel. While we leverage
> many different technique, the notable feature of RaceFuzzer is in
> leveraging a custom hypervisor (QEMU/KVM) to interleave the
> scheduling. In particular, we modified the hypervisor to intentionally
> stall a per-core execution, which is similar to supporting per-core
> breakpoint functionality. This allows RaceFuzzer to force the kernel
> to deterministically trigger racy condition (which may rarely happen
> in practice due to randomness in scheduling).
>
> RaceFuzzer's C repro always pinpoints two racy syscalls. Since C
> repro's scheduling synchronization should be performed at the user
> space, its reproducibility is limited (reproduction may take from 1
> second to 10 minutes (or even more), depending on a bug). This is
> because, while RaceFuzzer precisely interleaves the scheduling at the
> kernel's instruction level when finding this bug, C repro cannot fully
> utilize such a feature. Please disregard all code related to
> "should_hypercall" in the C repro, as this is only for our debugging
> purposes using our own hypervisor.
^ permalink raw reply
* [PATCH v6 5/5] mailbox: Add support for i.MX7D messaging unit
From: Oleksij Rempel @ 2018-07-24 5:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1532366380.3163.109.camel@pengutronix.de>
Hi Lucas,
here is more detailed response:
On 23.07.2018 19:19, Lucas Stach wrote:
> Am Sonntag, den 22.07.2018, 08:39 +0200 schrieb Oleksij Rempel:
>> The Mailbox controller is able to send messages (up to 4 32 bit words)
>> between the endpoints.
>>
>> This driver was tested using the mailbox-test driver sending messages
>> between the Cortex-A7 and the Cortex-M4.
>>
>>> Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>> ?drivers/mailbox/Kconfig???????|???6 +
>> ?drivers/mailbox/Makefile??????|???2 +
>> ?drivers/mailbox/imx-mailbox.c | 273 ++++++++++++++++++++++++++++++++++
>> ?3 files changed, 281 insertions(+)
>> ?create mode 100644 drivers/mailbox/imx-mailbox.c
>>
>> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
>> index a2bb27446dce..79060ddc380d 100644
>> --- a/drivers/mailbox/Kconfig
>> +++ b/drivers/mailbox/Kconfig
>> @@ -15,6 +15,12 @@ config ARM_MHU
>>> ? ??The controller has 3 mailbox channels, the last of which can be
>>> ? ??used in Secure mode only.
>> ?
>> +config IMX_MBOX
>>> + tristate "i.MX Mailbox"
>>> + depends on ARCH_MXC || COMPILE_TEST
>>> + help
>>> + ??Mailbox implementation for i.MX Messaging Unit (MU).
>> +
>> ?config PLATFORM_MHU
>>> ? tristate "Platform MHU Mailbox"
>>> ? depends on OF
>> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
>> index cc23c3a43fcd..ba2fe1b6dd62 100644
>> --- a/drivers/mailbox/Makefile
>> +++ b/drivers/mailbox/Makefile
>>> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o
>> ?
>>> ?obj-$(CONFIG_ARM_MHU) += arm_mhu.o
>> ?
>>> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
>> +
>>> ?obj-$(CONFIG_PLATFORM_MHU) += platform_mhu.o
>> ?
>>> ?obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
>> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
>> new file mode 100644
>> index 000000000000..29cf2876db01
>> --- /dev/null
>> +++ b/drivers/mailbox/imx-mailbox.c
>> @@ -0,0 +1,273 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mailbox_controller.h>
>> +#include <linux/module.h>
>> +#include <linux/of_device.h>
>> +
>> +/* Transmit Register */
>>> +#define IMX_MU_xTRn(x) (0x00 + 4 * (x))
>> +/* Receive Register */
>>> +#define IMX_MU_xRRn(x) (0x10 + 4 * (x))
>> +/* Status Register */
>>> +#define IMX_MU_xSR 0x20
>>> +#define IMX_MU_xSR_TEn(x) BIT(20 + (3 - (x)))
>>> +#define IMX_MU_xSR_RFn(x) BIT(24 + (3 - (x)))
>>> +#define IMX_MU_xSR_BRDIP BIT(9)
>> +
>> +/* Control Register */
>>> +#define IMX_MU_xCR 0x24
>> +/* Transmit Interrupt Enable */
>>> +#define IMX_MU_xCR_TIEn(x) BIT(20 + (3 - (x)))
>> +/* Receive Interrupt Enable */
>>> +#define IMX_MU_xCR_RIEn(x) BIT(24 + (3 - (x)))
>> +
>>> +#define IMX_MU_CHANS 4u
>> +
>> +struct imx_mu_con_priv {
>>>> + int irq;
>>>> + unsigned int idx;
>>>> + char *irq_desc;
>> +};
>> +
>> +struct imx_mu_priv {
>>>> + struct device *dev;
>>>> + void __iomem *base;
>> +
>>>> + struct mbox_controller mbox;
>>>> + struct mbox_chan mbox_chans[IMX_MU_CHANS];
>> +
>>> + struct imx_mu_con_priv??con_priv[IMX_MU_CHANS];
>>>> + struct clk *clk;
>> +
>>>> + bool side_b;
>> +};
>> +
>> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
>> +{
>>> + return container_of(mbox, struct imx_mu_priv, mbox);
>> +}
>> +
>> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
>> +{
>> + iowrite32(val, priv->base + offs);
>
> This driver is never going to be used on a device with port based IO,
> so iowrite doesn't make much sense here, just use writel. Same comment
> applies to the below read function.
As before I don't really understand the difference. I took some time for
learning and here are my findings:
- historical background of ioread/iowrite functions. What I can find is
this LWN article: https://lwn.net/Articles/102232/ . The main point
seems to be "The first of these is a new __iomem annotation used to mark
pointers to I/O memory" ... " As with __user, the __iomem marker serves
a documentation role in the kernel code;"
In modern kernel the difference between ioread32 and readl seems to be
completely disappeared.
with this LWN article (2016):
https://lwn.net/Articles/698014/
the readl and reade32 are always in the same group..
If there is some documentation which will say why I should use readl()
instead of ioread32() i would really love to read it.
> Also, given that those functions are not really shortening the code in
> the user they may also be removed completely IMHO.
Wrong assumption.. I use this functions for tracing. It is just to easy
to add two trace points... From technical perspective I don't see any
advantage or disadvantage of having this functions.
If it is my personal preference, then I decide to keep it.
>> +}
>> +
>> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
>> +{
>>> + return ioread32(priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
>> +{
>>> + u32 val;
>> +
>>> + val = imx_mu_read(priv, offs);
>>> + val &= ~clr;
>>> + val |= set;
>>> + imx_mu_write(priv, val, offs);
>> +
>>> + return val;
>> +}
>> +
>> +static irqreturn_t imx_mu_isr(int irq, void *p)
>> +{
>>> + struct mbox_chan *chan = p;
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + u32 val, ctrl, dat;
>> +
>>> + ctrl = imx_mu_read(priv, IMX_MU_xCR);
>>> + val = imx_mu_read(priv, IMX_MU_xSR);
>>> + val &= IMX_MU_xSR_TEn(cp->idx) | IMX_MU_xSR_RFn(cp->idx);
>>> + val &= ctrl & (IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx));
>>> + if (!val)
>>> + return IRQ_NONE;
>> +
>>> + if (val & IMX_MU_xSR_TEn(cp->idx)) {
>>> + imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->idx));
>>> + mbox_chan_txdone(chan, 0);
>>> + }
>> +
>>> + if (val & IMX_MU_xSR_RFn(cp->idx)) {
>>> + dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
>>> + mbox_chan_received_data(chan, (void *)&dat);
>>> + }
>> +
>>> + return IRQ_HANDLED;
>> +}
>> +
>> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + u32 val;
>> +
>>> + val = imx_mu_read(priv, IMX_MU_xSR);
>>> + /* test if transmit register is empty */
>> + return val & IMX_MU_xSR_TEn(cp->idx);
>
> I guess
> "return imx_mu_read(priv, IMX_MU_xSR) & IMX_MU_xSR_TEn(cp->idx);" is
> shorter and equally well understood.
So, previous comment was saying, "those functions are not really
shortening the code"
I would apply same comment: "those .. are not really shortening the code".
Do we really need to make review of "personal coding style
preferences".. which are not against kernel coding style in 6. review
round...?!
For example:
kernel coding style is pink... in this case we are talking about
difference between lavender pink and carnation pink.
>> +}
>> +
>> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + u32 *arg = data;
>> +
>>> + if (!imx_mu_last_tx_done(chan))
>>> + return -EBUSY;
>> +
>>> + imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
>> + imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->idx), 0);
>
> In multi-channel mode this RMW cycle needs some kind of locking. As
> this register is also changed from the irq handler, this probably needs
> to be a irqsave spinlock.
Thank you, i need to fix it.
>> +
>>> + return 0;
>> +}
>> +
>> +static int imx_mu_startup(struct mbox_chan *chan)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + int ret;
>> +
>>> + cp->irq_desc = devm_kasprintf(priv->dev, GFP_KERNEL, "imx_mu_chan[%i]",
>>> + ??????cp->idx);
>>> + if (!cp->irq_desc)
>>> + return -ENOMEM;
>> +
>>> + ret = devm_request_irq(priv->dev, cp->irq, imx_mu_isr,
>> + ???????IRQF_SHARED, cp->irq_desc, chan);
>
> Using the devm_ variants of those functions doesn't make sense when the
> resources aren't tied to the device lifetime. As you are tearing them
> down manually in imx_mu_shutdown anyways, just use the raw variants of
> those functions.
I have nothing against it.
>> + if (ret) {
>>> + dev_err(priv->dev,
>>> + "Unable to acquire IRQ %d\n", cp->irq);
>>> + return ret;
>>> + }
>> +
>>> + imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->idx), 0);
>> +
>>> + return 0;
>> +}
>> +
>> +static void imx_mu_shutdown(struct mbox_chan *chan)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>> +
>>> + imx_mu_rmw(priv, IMX_MU_xCR, 0,
>>> + ???IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx));
>> +
>>> + devm_free_irq(priv->dev, cp->irq, chan);
>>> + devm_kfree(priv->dev, cp->irq_desc);
>> +}
>> +
>> +static const struct mbox_chan_ops imx_mu_ops = {
>>> + .send_data = imx_mu_send_data,
>>> + .startup = imx_mu_startup,
>>> + .shutdown = imx_mu_shutdown,
>> +};
>> +
>> +static void imx_mu_init_generic(struct imx_mu_priv *priv)
>> +{
>>> + if (priv->side_b)
>>> + return;
>> +
>>> + /* Set default MU configuration */
>>> + imx_mu_write(priv, 0, IMX_MU_xCR);
>> +}
>> +
>> +static int imx_mu_probe(struct platform_device *pdev)
>> +{
>>> + struct device *dev = &pdev->dev;
>>> + struct device_node *np = dev->of_node;
>>> + struct resource *iomem;
>>> + struct imx_mu_priv *priv;
>>> + unsigned int i;
>>> + int irq, ret;
>> +
>>> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>> + if (!priv)
>>> + return -ENOMEM;
>> +
>>> + priv->dev = dev;
>> +
>>> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> + priv->base = devm_ioremap_resource(&pdev->dev, iomem);
>>> + if (IS_ERR(priv->base))
>>> + return PTR_ERR(priv->base);
>> +
>>> + irq = platform_get_irq(pdev, 0);
>>> + if (irq < 0)
>>> + return irq;
>> +
>>> + priv->clk = devm_clk_get(dev, NULL);
>>> + if (IS_ERR(priv->clk)) {
>>> + if (PTR_ERR(priv->clk) != -ENOENT)
>>> + return PTR_ERR(priv->clk);
>> +
>>> + priv->clk = NULL;
>>> + }
>> +
>>> + ret = clk_prepare_enable(priv->clk);
>>> + if (ret) {
>>> + dev_err(dev, "Failed to enable clock\n");
>>> + return ret;
>>> + }
>> +
>>> + for (i = 0; i < IMX_MU_CHANS; i++) {
>>> + struct imx_mu_con_priv *cp = &priv->con_priv[i];
>> +
>>> + cp->idx = i;
>>> + cp->irq = irq;
>>> + priv->mbox_chans[i].con_priv = cp;
>>> + }
>> +
>>> + if (of_property_read_bool(np, "fsl,mu-side-b"))
>> + priv->side_b = true;
>
> No need for the if clause here. Just assign the return value from
> of_property_read_bool to priv->side_b.
ok.
Thank you for a review!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180724/8a7ff5f5/attachment-0001.sig>
^ permalink raw reply
* Re: [PATCH v6 5/5] mailbox: Add support for i.MX7D messaging unit
From: Oleksij Rempel @ 2018-07-24 5:14 UTC (permalink / raw)
To: Lucas Stach, Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland,
A.s. Dong, Vladimir Zapolskiy
Cc: kernel, devicetree, dl-linux-imx, linux-arm-kernel
In-Reply-To: <1532366380.3163.109.camel@pengutronix.de>
[-- Attachment #1.1.1: Type: text/plain, Size: 11316 bytes --]
Hi Lucas,
here is more detailed response:
On 23.07.2018 19:19, Lucas Stach wrote:
> Am Sonntag, den 22.07.2018, 08:39 +0200 schrieb Oleksij Rempel:
>> The Mailbox controller is able to send messages (up to 4 32 bit words)
>> between the endpoints.
>>
>> This driver was tested using the mailbox-test driver sending messages
>> between the Cortex-A7 and the Cortex-M4.
>>
>>> Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>
>>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>> drivers/mailbox/Kconfig | 6 +
>> drivers/mailbox/Makefile | 2 +
>> drivers/mailbox/imx-mailbox.c | 273 ++++++++++++++++++++++++++++++++++
>> 3 files changed, 281 insertions(+)
>> create mode 100644 drivers/mailbox/imx-mailbox.c
>>
>> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
>> index a2bb27446dce..79060ddc380d 100644
>> --- a/drivers/mailbox/Kconfig
>> +++ b/drivers/mailbox/Kconfig
>> @@ -15,6 +15,12 @@ config ARM_MHU
>>> The controller has 3 mailbox channels, the last of which can be
>>> used in Secure mode only.
>>
>> +config IMX_MBOX
>>> + tristate "i.MX Mailbox"
>>> + depends on ARCH_MXC || COMPILE_TEST
>>> + help
>>> + Mailbox implementation for i.MX Messaging Unit (MU).
>> +
>> config PLATFORM_MHU
>>> tristate "Platform MHU Mailbox"
>>> depends on OF
>> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
>> index cc23c3a43fcd..ba2fe1b6dd62 100644
>> --- a/drivers/mailbox/Makefile
>> +++ b/drivers/mailbox/Makefile
>>> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o
>>
>>> obj-$(CONFIG_ARM_MHU) += arm_mhu.o
>>
>>> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
>> +
>>> obj-$(CONFIG_PLATFORM_MHU) += platform_mhu.o
>>
>>> obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
>> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
>> new file mode 100644
>> index 000000000000..29cf2876db01
>> --- /dev/null
>> +++ b/drivers/mailbox/imx-mailbox.c
>> @@ -0,0 +1,273 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mailbox_controller.h>
>> +#include <linux/module.h>
>> +#include <linux/of_device.h>
>> +
>> +/* Transmit Register */
>>> +#define IMX_MU_xTRn(x) (0x00 + 4 * (x))
>> +/* Receive Register */
>>> +#define IMX_MU_xRRn(x) (0x10 + 4 * (x))
>> +/* Status Register */
>>> +#define IMX_MU_xSR 0x20
>>> +#define IMX_MU_xSR_TEn(x) BIT(20 + (3 - (x)))
>>> +#define IMX_MU_xSR_RFn(x) BIT(24 + (3 - (x)))
>>> +#define IMX_MU_xSR_BRDIP BIT(9)
>> +
>> +/* Control Register */
>>> +#define IMX_MU_xCR 0x24
>> +/* Transmit Interrupt Enable */
>>> +#define IMX_MU_xCR_TIEn(x) BIT(20 + (3 - (x)))
>> +/* Receive Interrupt Enable */
>>> +#define IMX_MU_xCR_RIEn(x) BIT(24 + (3 - (x)))
>> +
>>> +#define IMX_MU_CHANS 4u
>> +
>> +struct imx_mu_con_priv {
>>>> + int irq;
>>>> + unsigned int idx;
>>>> + char *irq_desc;
>> +};
>> +
>> +struct imx_mu_priv {
>>>> + struct device *dev;
>>>> + void __iomem *base;
>> +
>>>> + struct mbox_controller mbox;
>>>> + struct mbox_chan mbox_chans[IMX_MU_CHANS];
>> +
>>> + struct imx_mu_con_priv con_priv[IMX_MU_CHANS];
>>>> + struct clk *clk;
>> +
>>>> + bool side_b;
>> +};
>> +
>> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
>> +{
>>> + return container_of(mbox, struct imx_mu_priv, mbox);
>> +}
>> +
>> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
>> +{
>> + iowrite32(val, priv->base + offs);
>
> This driver is never going to be used on a device with port based IO,
> so iowrite doesn't make much sense here, just use writel. Same comment
> applies to the below read function.
As before I don't really understand the difference. I took some time for
learning and here are my findings:
- historical background of ioread/iowrite functions. What I can find is
this LWN article: https://lwn.net/Articles/102232/ . The main point
seems to be "The first of these is a new __iomem annotation used to mark
pointers to I/O memory" ... " As with __user, the __iomem marker serves
a documentation role in the kernel code;"
In modern kernel the difference between ioread32 and readl seems to be
completely disappeared.
with this LWN article (2016):
https://lwn.net/Articles/698014/
the readl and reade32 are always in the same group..
If there is some documentation which will say why I should use readl()
instead of ioread32() i would really love to read it.
> Also, given that those functions are not really shortening the code in
> the user they may also be removed completely IMHO.
Wrong assumption.. I use this functions for tracing. It is just to easy
to add two trace points... From technical perspective I don't see any
advantage or disadvantage of having this functions.
If it is my personal preference, then I decide to keep it.
>> +}
>> +
>> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
>> +{
>>> + return ioread32(priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
>> +{
>>> + u32 val;
>> +
>>> + val = imx_mu_read(priv, offs);
>>> + val &= ~clr;
>>> + val |= set;
>>> + imx_mu_write(priv, val, offs);
>> +
>>> + return val;
>> +}
>> +
>> +static irqreturn_t imx_mu_isr(int irq, void *p)
>> +{
>>> + struct mbox_chan *chan = p;
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + u32 val, ctrl, dat;
>> +
>>> + ctrl = imx_mu_read(priv, IMX_MU_xCR);
>>> + val = imx_mu_read(priv, IMX_MU_xSR);
>>> + val &= IMX_MU_xSR_TEn(cp->idx) | IMX_MU_xSR_RFn(cp->idx);
>>> + val &= ctrl & (IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx));
>>> + if (!val)
>>> + return IRQ_NONE;
>> +
>>> + if (val & IMX_MU_xSR_TEn(cp->idx)) {
>>> + imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->idx));
>>> + mbox_chan_txdone(chan, 0);
>>> + }
>> +
>>> + if (val & IMX_MU_xSR_RFn(cp->idx)) {
>>> + dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
>>> + mbox_chan_received_data(chan, (void *)&dat);
>>> + }
>> +
>>> + return IRQ_HANDLED;
>> +}
>> +
>> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + u32 val;
>> +
>>> + val = imx_mu_read(priv, IMX_MU_xSR);
>>> + /* test if transmit register is empty */
>> + return val & IMX_MU_xSR_TEn(cp->idx);
>
> I guess
> "return imx_mu_read(priv, IMX_MU_xSR) & IMX_MU_xSR_TEn(cp->idx);" is
> shorter and equally well understood.
So, previous comment was saying, "those functions are not really
shortening the code"
I would apply same comment: "those .. are not really shortening the code".
Do we really need to make review of "personal coding style
preferences".. which are not against kernel coding style in 6. review
round...?!
For example:
kernel coding style is pink... in this case we are talking about
difference between lavender pink and carnation pink.
>> +}
>> +
>> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + u32 *arg = data;
>> +
>>> + if (!imx_mu_last_tx_done(chan))
>>> + return -EBUSY;
>> +
>>> + imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
>> + imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->idx), 0);
>
> In multi-channel mode this RMW cycle needs some kind of locking. As
> this register is also changed from the irq handler, this probably needs
> to be a irqsave spinlock.
Thank you, i need to fix it.
>> +
>>> + return 0;
>> +}
>> +
>> +static int imx_mu_startup(struct mbox_chan *chan)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>>> + int ret;
>> +
>>> + cp->irq_desc = devm_kasprintf(priv->dev, GFP_KERNEL, "imx_mu_chan[%i]",
>>> + cp->idx);
>>> + if (!cp->irq_desc)
>>> + return -ENOMEM;
>> +
>>> + ret = devm_request_irq(priv->dev, cp->irq, imx_mu_isr,
>> + IRQF_SHARED, cp->irq_desc, chan);
>
> Using the devm_ variants of those functions doesn't make sense when the
> resources aren't tied to the device lifetime. As you are tearing them
> down manually in imx_mu_shutdown anyways, just use the raw variants of
> those functions.
I have nothing against it.
>> + if (ret) {
>>> + dev_err(priv->dev,
>>> + "Unable to acquire IRQ %d\n", cp->irq);
>>> + return ret;
>>> + }
>> +
>>> + imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->idx), 0);
>> +
>>> + return 0;
>> +}
>> +
>> +static void imx_mu_shutdown(struct mbox_chan *chan)
>> +{
>>> + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>>> + struct imx_mu_con_priv *cp = chan->con_priv;
>> +
>>> + imx_mu_rmw(priv, IMX_MU_xCR, 0,
>>> + IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx));
>> +
>>> + devm_free_irq(priv->dev, cp->irq, chan);
>>> + devm_kfree(priv->dev, cp->irq_desc);
>> +}
>> +
>> +static const struct mbox_chan_ops imx_mu_ops = {
>>> + .send_data = imx_mu_send_data,
>>> + .startup = imx_mu_startup,
>>> + .shutdown = imx_mu_shutdown,
>> +};
>> +
>> +static void imx_mu_init_generic(struct imx_mu_priv *priv)
>> +{
>>> + if (priv->side_b)
>>> + return;
>> +
>>> + /* Set default MU configuration */
>>> + imx_mu_write(priv, 0, IMX_MU_xCR);
>> +}
>> +
>> +static int imx_mu_probe(struct platform_device *pdev)
>> +{
>>> + struct device *dev = &pdev->dev;
>>> + struct device_node *np = dev->of_node;
>>> + struct resource *iomem;
>>> + struct imx_mu_priv *priv;
>>> + unsigned int i;
>>> + int irq, ret;
>> +
>>> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>> + if (!priv)
>>> + return -ENOMEM;
>> +
>>> + priv->dev = dev;
>> +
>>> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> + priv->base = devm_ioremap_resource(&pdev->dev, iomem);
>>> + if (IS_ERR(priv->base))
>>> + return PTR_ERR(priv->base);
>> +
>>> + irq = platform_get_irq(pdev, 0);
>>> + if (irq < 0)
>>> + return irq;
>> +
>>> + priv->clk = devm_clk_get(dev, NULL);
>>> + if (IS_ERR(priv->clk)) {
>>> + if (PTR_ERR(priv->clk) != -ENOENT)
>>> + return PTR_ERR(priv->clk);
>> +
>>> + priv->clk = NULL;
>>> + }
>> +
>>> + ret = clk_prepare_enable(priv->clk);
>>> + if (ret) {
>>> + dev_err(dev, "Failed to enable clock\n");
>>> + return ret;
>>> + }
>> +
>>> + for (i = 0; i < IMX_MU_CHANS; i++) {
>>> + struct imx_mu_con_priv *cp = &priv->con_priv[i];
>> +
>>> + cp->idx = i;
>>> + cp->irq = irq;
>>> + priv->mbox_chans[i].con_priv = cp;
>>> + }
>> +
>>> + if (of_property_read_bool(np, "fsl,mu-side-b"))
>> + priv->side_b = true;
>
> No need for the if clause here. Just assign the return value from
> of_property_read_bool to priv->side_b.
ok.
Thank you for a review!
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.