From 40a669739ac76e9076331397ed23592a8d66fb28 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 6 Nov 2018 12:04:38 +0200 Subject: mei: hbm: drop BUG() from the hbm handler Drop BUG() from the hbm handler in order not to crash the whole kernel on faulty firmware implementation. Instead of it, just return an error resulting into link reset. There is no any known issue of faulty firmware in this matter, the change is just to ease the development. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hbm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index e56f3e72d57a..fe67381b34c3 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -1271,8 +1271,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) break; default: - BUG(); - break; + WARN(1, "hbm: wrong command %d\n", mei_msg->hbm_cmd); + return -EPROTO; } return 0; -- cgit v1.2.3 From 87d63352b49e421bb272dbb553bcf7db316c168f Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 6 Nov 2018 12:04:39 +0200 Subject: mei: flush queues by the host client only During queues flush, the me client in most cases is already unlinked hence the me client id is unavailable. The host client structure pointer is enough for identification. The function mei_cl_cmp_id() is dropped as it has no more usage. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index ebdcf0b450e2..ee58561ceb08 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -317,23 +317,6 @@ void mei_me_cl_rm_all(struct mei_device *dev) up_write(&dev->me_clients_rwsem); } -/** - * mei_cl_cmp_id - tells if the clients are the same - * - * @cl1: host client 1 - * @cl2: host client 2 - * - * Return: true - if the clients has same host and me ids - * false - otherwise - */ -static inline bool mei_cl_cmp_id(const struct mei_cl *cl1, - const struct mei_cl *cl2) -{ - return cl1 && cl2 && - (cl1->host_client_id == cl2->host_client_id) && - (mei_cl_me_id(cl1) == mei_cl_me_id(cl2)); -} - /** * mei_io_cb_free - free mei_cb_private related memory * @@ -418,7 +401,7 @@ static void mei_io_list_flush_cl(struct list_head *head, struct mei_cl_cb *cb, *next; list_for_each_entry_safe(cb, next, head, list) { - if (mei_cl_cmp_id(cl, cb->cl)) + if (cl == cb->cl) list_del_init(&cb->list); } } @@ -435,7 +418,7 @@ static void mei_io_tx_list_free_cl(struct list_head *head, struct mei_cl_cb *cb, *next; list_for_each_entry_safe(cb, next, head, list) { - if (mei_cl_cmp_id(cl, cb->cl)) + if (cl == cb->cl) mei_tx_cb_dequeue(cb); } } -- cgit v1.2.3 From a19bf05359e6c5249766cbbf2937ef83fc9001f9 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 6 Nov 2018 12:04:40 +0200 Subject: mei: expedite ioctl return on the notify set operation error The notify set operation ioctl will wait till timeout is expired even in case when the FW returned an error. Check the status field of the client object in wait_event_timeout() to determine if the caller can return earlier. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index ee58561ceb08..1fe9426ce48b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1357,7 +1357,9 @@ int mei_cl_notify_request(struct mei_cl *cl, mutex_unlock(&dev->device_lock); wait_event_timeout(cl->wait, - cl->notify_en == request || !mei_cl_is_connected(cl), + cl->notify_en == request || + cl->status || + !mei_cl_is_connected(cl), mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); mutex_lock(&dev->device_lock); -- cgit v1.2.3 From fcb418cd567febb310749e37507679e4f2703e56 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:12 +0800 Subject: pvpanic: move pvpanic to misc as common driver Move pvpanic.c from drivers/platform/x86 to drivers/misc. Following patches will use pvpanic device in arm64. Reviewed-by: Andy Shevchenko Acked-by: Mark Rutland Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 8 +++ drivers/misc/Makefile | 1 + drivers/misc/pvpanic.c | 124 +++++++++++++++++++++++++++++++++++++++++ drivers/platform/x86/Kconfig | 8 --- drivers/platform/x86/Makefile | 1 - drivers/platform/x86/pvpanic.c | 124 ----------------------------------------- 6 files changed, 133 insertions(+), 133 deletions(-) create mode 100644 drivers/misc/pvpanic.c delete mode 100644 drivers/platform/x86/pvpanic.c (limited to 'drivers/misc') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 3726eacdf65d..64c898aec3b2 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -513,6 +513,14 @@ config MISC_RTSX tristate default MISC_RTSX_PCI || MISC_RTSX_USB +config PVPANIC + tristate "pvpanic device support" + depends on ACPI + help + This driver provides support for the pvpanic device. pvpanic is + a paravirtualized device provided by QEMU; it lets a virtual machine + (guest) communicate panic events to the host. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index af22bbc3d00c..b76d611c87de 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o obj-$(CONFIG_OCXL) += ocxl/ obj-$(CONFIG_MISC_RTSX) += cardreader/ +obj-$(CONFIG_PVPANIC) += pvpanic.o diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c new file mode 100644 index 000000000000..fd86daba7ffd --- /dev/null +++ b/drivers/misc/pvpanic.c @@ -0,0 +1,124 @@ +/* + * pvpanic.c - pvpanic Device Support + * + * Copyright (C) 2013 Fujitsu. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Hu Tao "); +MODULE_DESCRIPTION("pvpanic device driver"); +MODULE_LICENSE("GPL"); + +static int pvpanic_add(struct acpi_device *device); +static int pvpanic_remove(struct acpi_device *device); + +static const struct acpi_device_id pvpanic_device_ids[] = { + { "QEMU0001", 0 }, + { "", 0 }, +}; +MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids); + +#define PVPANIC_PANICKED (1 << 0) + +static u16 port; + +static struct acpi_driver pvpanic_driver = { + .name = "pvpanic", + .class = "QEMU", + .ids = pvpanic_device_ids, + .ops = { + .add = pvpanic_add, + .remove = pvpanic_remove, + }, + .owner = THIS_MODULE, +}; + +static void +pvpanic_send_event(unsigned int event) +{ + outb(event, port); +} + +static int +pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, + void *unused) +{ + pvpanic_send_event(PVPANIC_PANICKED); + return NOTIFY_DONE; +} + +static struct notifier_block pvpanic_panic_nb = { + .notifier_call = pvpanic_panic_notify, + .priority = 1, /* let this called before broken drm_fb_helper */ +}; + + +static acpi_status +pvpanic_walk_resources(struct acpi_resource *res, void *context) +{ + switch (res->type) { + case ACPI_RESOURCE_TYPE_END_TAG: + return AE_OK; + + case ACPI_RESOURCE_TYPE_IO: + port = res->data.io.minimum; + return AE_OK; + + default: + return AE_ERROR; + } +} + +static int pvpanic_add(struct acpi_device *device) +{ + int ret; + + ret = acpi_bus_get_status(device); + if (ret < 0) + return ret; + + if (!device->status.enabled || !device->status.functional) + return -ENODEV; + + acpi_walk_resources(device->handle, METHOD_NAME__CRS, + pvpanic_walk_resources, NULL); + + if (!port) + return -ENODEV; + + atomic_notifier_chain_register(&panic_notifier_list, + &pvpanic_panic_nb); + + return 0; +} + +static int pvpanic_remove(struct acpi_device *device) +{ + + atomic_notifier_chain_unregister(&panic_notifier_list, + &pvpanic_panic_nb); + return 0; +} + +module_acpi_driver(pvpanic_driver); diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 54f6a40c75c6..5d5ee4fa1e6e 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1168,14 +1168,6 @@ config INTEL_SMARTCONNECT This driver checks to determine whether the device has Intel Smart Connect enabled, and if so disables it. -config PVPANIC - tristate "pvpanic device support" - depends on ACPI - ---help--- - This driver provides support for the pvpanic device. pvpanic is - a paravirtualized device provided by QEMU; it lets a virtual machine - (guest) communicate panic events to the host. - config INTEL_PMC_IPC tristate "Intel PMC IPC Driver" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 39ae94135406..d537d1753147 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -78,7 +78,6 @@ obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o obj-$(CONFIG_INTEL_RST) += intel-rst.o obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o -obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o diff --git a/drivers/platform/x86/pvpanic.c b/drivers/platform/x86/pvpanic.c deleted file mode 100644 index fd86daba7ffd..000000000000 --- a/drivers/platform/x86/pvpanic.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * pvpanic.c - pvpanic Device Support - * - * Copyright (C) 2013 Fujitsu. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Hu Tao "); -MODULE_DESCRIPTION("pvpanic device driver"); -MODULE_LICENSE("GPL"); - -static int pvpanic_add(struct acpi_device *device); -static int pvpanic_remove(struct acpi_device *device); - -static const struct acpi_device_id pvpanic_device_ids[] = { - { "QEMU0001", 0 }, - { "", 0 }, -}; -MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids); - -#define PVPANIC_PANICKED (1 << 0) - -static u16 port; - -static struct acpi_driver pvpanic_driver = { - .name = "pvpanic", - .class = "QEMU", - .ids = pvpanic_device_ids, - .ops = { - .add = pvpanic_add, - .remove = pvpanic_remove, - }, - .owner = THIS_MODULE, -}; - -static void -pvpanic_send_event(unsigned int event) -{ - outb(event, port); -} - -static int -pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, - void *unused) -{ - pvpanic_send_event(PVPANIC_PANICKED); - return NOTIFY_DONE; -} - -static struct notifier_block pvpanic_panic_nb = { - .notifier_call = pvpanic_panic_notify, - .priority = 1, /* let this called before broken drm_fb_helper */ -}; - - -static acpi_status -pvpanic_walk_resources(struct acpi_resource *res, void *context) -{ - switch (res->type) { - case ACPI_RESOURCE_TYPE_END_TAG: - return AE_OK; - - case ACPI_RESOURCE_TYPE_IO: - port = res->data.io.minimum; - return AE_OK; - - default: - return AE_ERROR; - } -} - -static int pvpanic_add(struct acpi_device *device) -{ - int ret; - - ret = acpi_bus_get_status(device); - if (ret < 0) - return ret; - - if (!device->status.enabled || !device->status.functional) - return -ENODEV; - - acpi_walk_resources(device->handle, METHOD_NAME__CRS, - pvpanic_walk_resources, NULL); - - if (!port) - return -ENODEV; - - atomic_notifier_chain_register(&panic_notifier_list, - &pvpanic_panic_nb); - - return 0; -} - -static int pvpanic_remove(struct acpi_device *device) -{ - - atomic_notifier_chain_unregister(&panic_notifier_list, - &pvpanic_panic_nb); - return 0; -} - -module_acpi_driver(pvpanic_driver); -- cgit v1.2.3 From d2ae1717f3f6b1bd86cd05d0443169b645445d62 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:13 +0800 Subject: misc/pvpanic: simplify the code using acpi_dev_resource_io Use acpi_dev_resource_io API. Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Acked-by: Mark Rutland Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index fd86daba7ffd..49c59e1d299d 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -77,17 +77,14 @@ static struct notifier_block pvpanic_panic_nb = { static acpi_status pvpanic_walk_resources(struct acpi_resource *res, void *context) { - switch (res->type) { - case ACPI_RESOURCE_TYPE_END_TAG: - return AE_OK; + struct resource r; - case ACPI_RESOURCE_TYPE_IO: - port = res->data.io.minimum; + if (acpi_dev_resource_io(res, &r)) { + port = r.start; return AE_OK; - - default: - return AE_ERROR; } + + return AE_ERROR; } static int pvpanic_add(struct acpi_device *device) -- cgit v1.2.3 From 725eba2928ada8d0fe6bafb984e37576851edc91 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:14 +0800 Subject: misc/pvpanic: add MMIO support On some architectures (e.g. arm64), it's preferable to use MMIO, since this can be used standalone. Add MMIO support to the pvpanic driver. Suggested-by: Andy Shevchenko [Use acpi_dev_resource_memory API. - Andy] Reviewed-by: Andy Shevchenko Acked-by: Mark Rutland Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index 49c59e1d299d..a46701c22b35 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -26,6 +26,8 @@ #include #include +static void __iomem *base; + MODULE_AUTHOR("Hu Tao "); MODULE_DESCRIPTION("pvpanic device driver"); MODULE_LICENSE("GPL"); @@ -41,8 +43,6 @@ MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids); #define PVPANIC_PANICKED (1 << 0) -static u16 port; - static struct acpi_driver pvpanic_driver = { .name = "pvpanic", .class = "QEMU", @@ -57,7 +57,7 @@ static struct acpi_driver pvpanic_driver = { static void pvpanic_send_event(unsigned int event) { - outb(event, port); + iowrite8(event, base); } static int @@ -80,7 +80,10 @@ pvpanic_walk_resources(struct acpi_resource *res, void *context) struct resource r; if (acpi_dev_resource_io(res, &r)) { - port = r.start; + base = ioport_map(r.start, resource_size(&r)); + return AE_OK; + } else if (acpi_dev_resource_memory(res, &r)) { + base = ioremap(r.start, resource_size(&r)); return AE_OK; } @@ -101,7 +104,7 @@ static int pvpanic_add(struct acpi_device *device) acpi_walk_resources(device->handle, METHOD_NAME__CRS, pvpanic_walk_resources, NULL); - if (!port) + if (!base) return -ENODEV; atomic_notifier_chain_register(&panic_notifier_list, @@ -115,6 +118,8 @@ static int pvpanic_remove(struct acpi_device *device) atomic_notifier_chain_unregister(&panic_notifier_list, &pvpanic_panic_nb); + iounmap(base); + return 0; } -- cgit v1.2.3 From 46f934c9a12fc565fe2ae82c709162fa002a2998 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:16 +0800 Subject: misc/pvpanic: add support to get pvpanic device info FDT By default, when ACPI tables and FDT coexist for ARM64, current kernel takes precedence over FDT to get device information. Virt machine in qemu provides both FDT and ACPI table. Increases the way to get information through FDT. Acked-by: Mark Rutland Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index a46701c22b35..fef76b5d5f0c 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -2,6 +2,7 @@ * pvpanic.c - pvpanic Device Support * * Copyright (C) 2013 Fujitsu. + * Copyright (C) 2018 ZTE. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +23,9 @@ #include #include +#include +#include +#include #include #include #include @@ -123,4 +127,62 @@ static int pvpanic_remove(struct acpi_device *device) return 0; } -module_acpi_driver(pvpanic_driver); +static int pvpanic_mmio_probe(struct platform_device *pdev) +{ + struct resource *mem; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -EINVAL; + + base = devm_ioremap_resource(&pdev->dev, mem); + if (base == NULL) + return -EFAULT; + + atomic_notifier_chain_register(&panic_notifier_list, + &pvpanic_panic_nb); + + return 0; +} + +static int pvpanic_mmio_remove(struct platform_device *pdev) +{ + + atomic_notifier_chain_unregister(&panic_notifier_list, + &pvpanic_panic_nb); + + return 0; +} + +static const struct of_device_id pvpanic_mmio_match[] = { + { .compatible = "qemu,pvpanic-mmio", }, + {} +}; + +static struct platform_driver pvpanic_mmio_driver = { + .driver = { + .name = "pvpanic-mmio", + .of_match_table = pvpanic_mmio_match, + }, + .probe = pvpanic_mmio_probe, + .remove = pvpanic_mmio_remove, +}; + +static int __init pvpanic_mmio_init(void) +{ + if (acpi_disabled) + return platform_driver_register(&pvpanic_mmio_driver); + else + return acpi_bus_register_driver(&pvpanic_driver); +} + +static void __exit pvpanic_mmio_exit(void) +{ + if (acpi_disabled) + platform_driver_unregister(&pvpanic_mmio_driver); + else + acpi_bus_unregister_driver(&pvpanic_driver); +} + +module_init(pvpanic_mmio_init); +module_exit(pvpanic_mmio_exit); -- cgit v1.2.3 From a8b71d2735791f09788a13dda928f690a417c14a Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:17 +0800 Subject: misc/pvpanic : grouping ACPI related stuff Grouping ACPI related stuff and make preparation to break the ACPI dependency w/o any functional change. Reviewed-by: Andy Shevchenko Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index fef76b5d5f0c..eabb53d077c5 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -32,32 +32,12 @@ static void __iomem *base; +#define PVPANIC_PANICKED (1 << 0) + MODULE_AUTHOR("Hu Tao "); MODULE_DESCRIPTION("pvpanic device driver"); MODULE_LICENSE("GPL"); -static int pvpanic_add(struct acpi_device *device); -static int pvpanic_remove(struct acpi_device *device); - -static const struct acpi_device_id pvpanic_device_ids[] = { - { "QEMU0001", 0 }, - { "", 0 }, -}; -MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids); - -#define PVPANIC_PANICKED (1 << 0) - -static struct acpi_driver pvpanic_driver = { - .name = "pvpanic", - .class = "QEMU", - .ids = pvpanic_device_ids, - .ops = { - .add = pvpanic_add, - .remove = pvpanic_remove, - }, - .owner = THIS_MODULE, -}; - static void pvpanic_send_event(unsigned int event) { @@ -77,6 +57,25 @@ static struct notifier_block pvpanic_panic_nb = { .priority = 1, /* let this called before broken drm_fb_helper */ }; +static int pvpanic_add(struct acpi_device *device); +static int pvpanic_remove(struct acpi_device *device); + +static const struct acpi_device_id pvpanic_device_ids[] = { + { "QEMU0001", 0 }, + { "", 0 }, +}; +MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids); + +static struct acpi_driver pvpanic_driver = { + .name = "pvpanic", + .class = "QEMU", + .ids = pvpanic_device_ids, + .ops = { + .add = pvpanic_add, + .remove = pvpanic_remove, + }, + .owner = THIS_MODULE, +}; static acpi_status pvpanic_walk_resources(struct acpi_resource *res, void *context) -- cgit v1.2.3 From 77703e0b0326a1fb06b5cb5b468a633472c5a8e9 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:18 +0800 Subject: misc/pvpanic : break dependency on ACPI The pvpanic driver is available for architectures that do not support ACPI.So break the dependency. Reviewed-by: Andy Shevchenko Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 2 +- drivers/misc/pvpanic.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 64c898aec3b2..642626ac1df1 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -515,7 +515,7 @@ config MISC_RTSX config PVPANIC tristate "pvpanic device support" - depends on ACPI + depends on ACPI || OF help This driver provides support for the pvpanic device. pvpanic is a paravirtualized device provided by QEMU; it lets a virtual machine diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index eabb53d077c5..aab06b890bb6 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -57,6 +57,7 @@ static struct notifier_block pvpanic_panic_nb = { .priority = 1, /* let this called before broken drm_fb_helper */ }; +#ifdef CONFIG_ACPI static int pvpanic_add(struct acpi_device *device); static int pvpanic_remove(struct acpi_device *device); @@ -126,6 +127,24 @@ static int pvpanic_remove(struct acpi_device *device) return 0; } +static int pvpanic_register_acpi_driver(void) +{ + return acpi_bus_register_driver(&pvpanic_driver); +} + +static void pvpanic_unregister_acpi_driver(void) +{ + acpi_bus_unregister_driver(&pvpanic_driver); +} +#else +static int pvpanic_register_acpi_driver(void) +{ + return -ENODEV; +} + +static void pvpanic_unregister_acpi_driver(void) {} +#endif + static int pvpanic_mmio_probe(struct platform_device *pdev) { struct resource *mem; @@ -172,7 +191,7 @@ static int __init pvpanic_mmio_init(void) if (acpi_disabled) return platform_driver_register(&pvpanic_mmio_driver); else - return acpi_bus_register_driver(&pvpanic_driver); + return pvpanic_register_acpi_driver(); } static void __exit pvpanic_mmio_exit(void) @@ -180,7 +199,7 @@ static void __exit pvpanic_mmio_exit(void) if (acpi_disabled) platform_driver_unregister(&pvpanic_mmio_driver); else - acpi_bus_unregister_driver(&pvpanic_driver); + pvpanic_unregister_acpi_driver(); } module_init(pvpanic_mmio_init); -- cgit v1.2.3 From bfebd5c222ddfce70dde0c2e18f6859f33891db3 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:19 +0800 Subject: misc/pvpanic: remove unnecessary header file Remove unnecessary header file init.h. Reviewed-by: Andy Shevchenko Acked-by: Mark Rutland Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index aab06b890bb6..b9402d9fea15 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 8eeffed038b92ff811364bf91acab4b2e6a47e7e Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:20 +0800 Subject: misc/pvpanic: change header file sort style Make header files alphabetical order. Signed-off-by: Peng Hao Reviewed-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index b9402d9fea15..3bfa0f5484d0 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -21,13 +21,13 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include #include #include #include -#include static void __iomem *base; -- cgit v1.2.3 From 7247932c7df2619d719175fc76327480c7259e80 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:21 +0800 Subject: misc/pvpanic: convert to SPDX license tags Updates license to use SPDX-License-Identifier instead of verbose license text. Reviewed-by: Andy Shevchenko Acked-by: Mark Rutland Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index 3bfa0f5484d0..47854f3c9f46 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * pvpanic.c - pvpanic Device Support + * Pvpanic Device Support * * Copyright (C) 2013 Fujitsu. * Copyright (C) 2018 ZTE. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -- cgit v1.2.3 From 78ef4193bbb97d17853f64a7975aa971d625c478 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Tue, 6 Nov 2018 22:57:22 +0800 Subject: misc/pvpanic: remove a redundant comma Remove a redundant comma in pvpanic_device_ids. Reviewed-by: Andy Shevchenko Acked-by: Mark Rutland Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index 47854f3c9f46..01241ec6a5cd 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -49,7 +49,7 @@ static int pvpanic_remove(struct acpi_device *device); static const struct acpi_device_id pvpanic_device_ids[] = { { "QEMU0001", 0 }, - { "", 0 }, + { "", 0 } }; MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids); -- cgit v1.2.3 From ce0925e8c2f85f6bbf5d24b56621336cceaf743d Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 22 Nov 2018 13:11:36 +0200 Subject: mei: dma ring buffers allocation Allocate DMA ring buffers from managed coherent memory. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/Makefile | 1 + drivers/misc/mei/dma-ring.c | 99 +++++++++++++++++++++++++++++++++++++++++++++ drivers/misc/mei/hw-me.c | 6 +++ drivers/misc/mei/mei_dev.h | 20 +++++++++ 4 files changed, 126 insertions(+) create mode 100644 drivers/misc/mei/dma-ring.c (limited to 'drivers/misc') diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile index cd6825afa8e1..d9215fc4e499 100644 --- a/drivers/misc/mei/Makefile +++ b/drivers/misc/mei/Makefile @@ -9,6 +9,7 @@ mei-objs += hbm.o mei-objs += interrupt.o mei-objs += client.o mei-objs += main.o +mei-objs += dma-ring.o mei-objs += bus.o mei-objs += bus-fixup.o mei-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/misc/mei/dma-ring.c b/drivers/misc/mei/dma-ring.c new file mode 100644 index 000000000000..56f4c0882a20 --- /dev/null +++ b/drivers/misc/mei/dma-ring.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. + */ +#include +#include + +#include "mei_dev.h" + +/** + * mei_dmam_dscr_alloc() - allocate a managed coherent buffer + * for the dma descriptor + * @dev: mei_device + * @dscr: dma descriptor + * + * Return: + * * 0 - on success or zero allocation request + * * -EINVAL - if size is not power of 2 + * * -ENOMEM - of allocation has failed + */ +static int mei_dmam_dscr_alloc(struct mei_device *dev, + struct mei_dma_dscr *dscr) +{ + if (!dscr->size) + return 0; + + if (WARN_ON(!is_power_of_2(dscr->size))) + return -EINVAL; + + if (dscr->vaddr) + return 0; + + dscr->vaddr = dmam_alloc_coherent(dev->dev, dscr->size, &dscr->daddr, + GFP_KERNEL); + if (!dscr->vaddr) + return -ENOMEM; + + return 0; +} + +/** + * mei_dmam_dscr_free() - free a managed coherent buffer + * from the dma descriptor + * @dev: mei_device + * @dscr: dma descriptor + */ +static void mei_dmam_dscr_free(struct mei_device *dev, + struct mei_dma_dscr *dscr) +{ + if (!dscr->vaddr) + return; + + dmam_free_coherent(dev->dev, dscr->size, dscr->vaddr, dscr->daddr); + dscr->vaddr = NULL; +} + +/** + * mei_dmam_ring_free() - free dma ring buffers + * @dev: mei device + */ +void mei_dmam_ring_free(struct mei_device *dev) +{ + int i; + + for (i = 0; i < DMA_DSCR_NUM; i++) + mei_dmam_dscr_free(dev, &dev->dr_dscr[i]); +} + +/** + * mei_dmam_ring_alloc() - allocate dma ring buffers + * @dev: mei device + * + * Return: -ENOMEM on allocation failure 0 otherwise + */ +int mei_dmam_ring_alloc(struct mei_device *dev) +{ + int i; + + for (i = 0; i < DMA_DSCR_NUM; i++) + if (mei_dmam_dscr_alloc(dev, &dev->dr_dscr[i])) + goto err; + + return 0; + +err: + mei_dmam_ring_free(dev); + return -ENOMEM; +} + +/** + * mei_dma_ring_is_allocated() - check if dma ring is allocated + * @dev: mei device + * + * Return: true if dma ring is allocated + */ +bool mei_dma_ring_is_allocated(struct mei_device *dev) +{ + return !!dev->dr_dscr[DMA_DSCR_HOST].vaddr; +} diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 0759c3a668de..3fbbadfa2ae1 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1471,15 +1471,21 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev, { struct mei_device *dev; struct mei_me_hw *hw; + int i; dev = devm_kzalloc(&pdev->dev, sizeof(struct mei_device) + sizeof(struct mei_me_hw), GFP_KERNEL); if (!dev) return NULL; + hw = to_me_hw(dev); + for (i = 0; i < DMA_DSCR_NUM; i++) + dev->dr_dscr[i].size = cfg->dma_size[i]; + mei_device_init(dev, &pdev->dev, &mei_me_hw_ops); hw->cfg = cfg; + return dev; } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 377397e1b5a5..a6796e3f712b 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -122,6 +122,19 @@ struct mei_msg_data { unsigned char *data; }; +/** + * struct mei_dma_dscr - dma address descriptor + * + * @vaddr: dma buffer virtual address + * @daddr: dma buffer physical address + * @size : dma buffer size + */ +struct mei_dma_dscr { + void *vaddr; + dma_addr_t daddr; + size_t size; +}; + /* Maximum number of processed FW status registers */ #define MEI_FW_STATUS_MAX 6 /* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */ @@ -409,6 +422,7 @@ struct mei_fw_version { * @rd_msg_hdr : read message header storage * * @hbuf_is_ready : query if the host host/write buffer is ready + * @dr_dscr: DMA ring descriptors: TX, RX, and CTRL * * @version : HBM protocol version in use * @hbm_f_pg_supported : hbm feature pgi protocol @@ -488,6 +502,8 @@ struct mei_device { /* write buffer */ bool hbuf_is_ready; + struct mei_dma_dscr dr_dscr[DMA_DSCR_NUM]; + struct hbm_version version; unsigned int hbm_f_pg_supported:1; unsigned int hbm_f_dc_supported:1; @@ -578,6 +594,10 @@ int mei_restart(struct mei_device *dev); void mei_stop(struct mei_device *dev); void mei_cancel_work(struct mei_device *dev); +int mei_dmam_ring_alloc(struct mei_device *dev); +void mei_dmam_ring_free(struct mei_device *dev); +bool mei_dma_ring_is_allocated(struct mei_device *dev); + /* * MEI interrupt functions prototype */ -- cgit v1.2.3 From c55bf542e91b5c9156d57fd0461aa257b7d20858 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 22 Nov 2018 13:11:37 +0200 Subject: mei: hbm: setup dma ring DMA ring is allocated upon HBM handshake and the ring parameters are set via dedicated HBM_DMA_SETUP request command. The firmware will perform its setup and respond with a status. On failure the DMA buffers are released. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hbm.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++-- drivers/misc/mei/hbm.h | 2 ++ 2 files changed, 85 insertions(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index fe67381b34c3..b458c5612245 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -65,6 +65,7 @@ const char *mei_hbm_state_str(enum mei_hbm_state state) MEI_HBM_STATE(IDLE); MEI_HBM_STATE(STARTING); MEI_HBM_STATE(STARTED); + MEI_HBM_STATE(DR_SETUP); MEI_HBM_STATE(ENUM_CLIENTS); MEI_HBM_STATE(CLIENT_PROPERTIES); MEI_HBM_STATE(STOPPED); @@ -295,6 +296,46 @@ int mei_hbm_start_req(struct mei_device *dev) return 0; } +/** + * mei_hbm_dma_setup_req() - setup DMA request + * @dev: the device structure + * + * Return: 0 on success and < 0 on failure + */ +static int mei_hbm_dma_setup_req(struct mei_device *dev) +{ + struct mei_msg_hdr mei_hdr; + struct hbm_dma_setup_request req; + const size_t len = sizeof(struct hbm_dma_setup_request); + unsigned int i; + int ret; + + mei_hbm_hdr(&mei_hdr, len); + + memset(&req, 0, len); + req.hbm_cmd = MEI_HBM_DMA_SETUP_REQ_CMD; + for (i = 0; i < DMA_DSCR_NUM; i++) { + phys_addr_t paddr; + + paddr = dev->dr_dscr[i].daddr; + req.dma_dscr[i].addr_hi = upper_32_bits(paddr); + req.dma_dscr[i].addr_lo = lower_32_bits(paddr); + req.dma_dscr[i].size = dev->dr_dscr[i].size; + } + + ret = mei_hbm_write_message(dev, &mei_hdr, &req); + if (ret) { + dev_err(dev->dev, "dma setup request write failed: ret = %d.\n", + ret); + return ret; + } + + dev->hbm_state = MEI_HBM_DR_SETUP; + dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; + mei_schedule_stall_timer(dev); + return 0; +} + /** * mei_hbm_enum_clients_req - sends enumeration client request message. * @@ -1044,6 +1085,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) struct hbm_host_version_response *version_res; struct hbm_props_response *props_res; struct hbm_host_enum_response *enum_res; + struct hbm_dma_setup_response *dma_setup_res; struct hbm_add_client_request *add_cl_req; int ret; @@ -1108,14 +1150,52 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) return -EPROTO; } - if (mei_hbm_enum_clients_req(dev)) { - dev_err(dev->dev, "hbm: start: failed to send enumeration request\n"); - return -EIO; + if (dev->hbm_f_dr_supported) { + if (mei_dmam_ring_alloc(dev)) + dev_info(dev->dev, "running w/o dma ring\n"); + if (mei_dma_ring_is_allocated(dev)) { + if (mei_hbm_dma_setup_req(dev)) + return -EIO; + + wake_up(&dev->wait_hbm_start); + break; + } } + dev->hbm_f_dr_supported = 0; + mei_dmam_ring_free(dev); + + if (mei_hbm_enum_clients_req(dev)) + return -EIO; + wake_up(&dev->wait_hbm_start); break; + case MEI_HBM_DMA_SETUP_RES_CMD: + dev_dbg(dev->dev, "hbm: dma setup response: message received.\n"); + + dev->init_clients_timer = 0; + + if (dev->hbm_state != MEI_HBM_DR_SETUP) { + dev_err(dev->dev, "hbm: dma setup response: state mismatch, [%d, %d]\n", + dev->dev_state, dev->hbm_state); + return -EPROTO; + } + + dma_setup_res = (struct hbm_dma_setup_response *)mei_msg; + + if (dma_setup_res->status) { + dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n", + dma_setup_res->status, + mei_hbm_status_str(dma_setup_res->status)); + dev->hbm_f_dr_supported = 0; + mei_dmam_ring_free(dev); + } + + if (mei_hbm_enum_clients_req(dev)) + return -EIO; + break; + case CLIENT_CONNECT_RES_CMD: dev_dbg(dev->dev, "hbm: client connect response: message received.\n"); mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_CONNECT); diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h index a2025a5083a3..0171a7e79bab 100644 --- a/drivers/misc/mei/hbm.h +++ b/drivers/misc/mei/hbm.h @@ -26,6 +26,7 @@ struct mei_cl; * * @MEI_HBM_IDLE : protocol not started * @MEI_HBM_STARTING : start request message was sent + * @MEI_HBM_DR_SETUP : dma ring setup request message was sent * @MEI_HBM_ENUM_CLIENTS : enumeration request was sent * @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties * @MEI_HBM_STARTED : enumeration was completed @@ -34,6 +35,7 @@ struct mei_cl; enum mei_hbm_state { MEI_HBM_IDLE = 0, MEI_HBM_STARTING, + MEI_HBM_DR_SETUP, MEI_HBM_ENUM_CLIENTS, MEI_HBM_CLIENT_PROPERTIES, MEI_HBM_STARTED, -- cgit v1.2.3 From 2513eb0dd7ba8a8766b9642075c19ac5f2d5463b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 22 Nov 2018 13:11:38 +0200 Subject: mei: hw: add dma ring control block The DMA ring control block contains write and read indices for host and device circular buffers. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/dma-ring.c | 20 ++++++++++++++++++++ drivers/misc/mei/hbm.c | 2 ++ drivers/misc/mei/hw.h | 23 +++++++++++++++++++++++ drivers/misc/mei/mei_dev.h | 1 + 4 files changed, 46 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/dma-ring.c b/drivers/misc/mei/dma-ring.c index 56f4c0882a20..b73d5ab54070 100644 --- a/drivers/misc/mei/dma-ring.c +++ b/drivers/misc/mei/dma-ring.c @@ -97,3 +97,23 @@ bool mei_dma_ring_is_allocated(struct mei_device *dev) { return !!dev->dr_dscr[DMA_DSCR_HOST].vaddr; } + +static inline +struct hbm_dma_ring_ctrl *mei_dma_ring_ctrl(struct mei_device *dev) +{ + return (struct hbm_dma_ring_ctrl *)dev->dr_dscr[DMA_DSCR_CTRL].vaddr; +} + +/** + * mei_dma_ring_reset() - reset the dma control block + * @dev: mei device + */ +void mei_dma_ring_reset(struct mei_device *dev) +{ + struct hbm_dma_ring_ctrl *ctrl = mei_dma_ring_ctrl(dev); + + if (!ctrl) + return; + + memset(ctrl, 0, sizeof(*ctrl)); +} diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index b458c5612245..78c26cebf5d4 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -323,6 +323,8 @@ static int mei_hbm_dma_setup_req(struct mei_device *dev) req.dma_dscr[i].size = dev->dr_dscr[i].size; } + mei_dma_ring_reset(dev); + ret = mei_hbm_write_message(dev, &mei_hdr, &req); if (ret) { dev_err(dev->dev, "dma setup request write failed: ret = %d.\n", diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 65655925791a..4f09bbcdbc2a 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -512,4 +512,27 @@ struct hbm_dma_setup_response { u8 reserved[2]; } __packed; +/** + * struct mei_dma_ring_ctrl - dma ring control block + * + * @hbuf_wr_idx: host circular buffer write index in slots + * @reserved1: reserved for alignment + * @hbuf_rd_idx: host circular buffer read index in slots + * @reserved2: reserved for alignment + * @dbuf_wr_idx: device circular buffer write index in slots + * @reserved3: reserved for alignment + * @dbuf_rd_idx: device circular buffer read index in slots + * @reserved4: reserved for alignment + */ +struct hbm_dma_ring_ctrl { + u32 hbuf_wr_idx; + u32 reserved1; + u32 hbuf_rd_idx; + u32 reserved2; + u32 dbuf_wr_idx; + u32 reserved3; + u32 dbuf_rd_idx; + u32 reserved4; +} __packed; + #endif diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index a6796e3f712b..033b5eff8e59 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -597,6 +597,7 @@ void mei_cancel_work(struct mei_device *dev); int mei_dmam_ring_alloc(struct mei_device *dev); void mei_dmam_ring_free(struct mei_device *dev); bool mei_dma_ring_is_allocated(struct mei_device *dev); +void mei_dma_ring_reset(struct mei_device *dev); /* * MEI interrupt functions prototype -- cgit v1.2.3 From 6316321f12ad30cf5af176f26bb39897b320ef46 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 22 Nov 2018 13:11:39 +0200 Subject: mei: dma ring: implement rx circular buffer logic Implement circular buffer protocol over receive dma buffer. Add extension to the mei message header that holds length of the buffer on the dma buffer. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 2 +- drivers/misc/mei/dma-ring.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ drivers/misc/mei/hw.h | 4 +++ drivers/misc/mei/init.c | 2 +- drivers/misc/mei/interrupt.c | 41 ++++++++++++++++++++--------- drivers/misc/mei/mei_dev.h | 3 ++- 6 files changed, 98 insertions(+), 15 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 1fe9426ce48b..5d15501af313 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -461,7 +461,7 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, if (length == 0) return cb; - cb->buf.data = kmalloc(length, GFP_KERNEL); + cb->buf.data = kmalloc(roundup(length, MEI_SLOT_SIZE), GFP_KERNEL); if (!cb->buf.data) { mei_io_cb_free(cb); return NULL; diff --git a/drivers/misc/mei/dma-ring.c b/drivers/misc/mei/dma-ring.c index b73d5ab54070..a0c40925049a 100644 --- a/drivers/misc/mei/dma-ring.c +++ b/drivers/misc/mei/dma-ring.c @@ -117,3 +117,64 @@ void mei_dma_ring_reset(struct mei_device *dev) memset(ctrl, 0, sizeof(*ctrl)); } + +/** + * mei_dma_copy_from() - copy from dma ring into buffer + * @dev: mei device + * @buf: data buffer + * @offset: offset in slots. + * @n: number of slots to copy. + */ +static size_t mei_dma_copy_from(struct mei_device *dev, unsigned char *buf, + u32 offset, u32 n) +{ + unsigned char *dbuf = dev->dr_dscr[DMA_DSCR_DEVICE].vaddr; + + size_t b_offset = offset << 2; + size_t b_n = n << 2; + + memcpy(buf, dbuf + b_offset, b_n); + + return b_n; +} + +/** + * mei_dma_ring_read() - read data from the ring + * @dev: mei device + * @buf: buffer to read into: may be NULL in case of droping the data. + * @len: length to read. + */ +void mei_dma_ring_read(struct mei_device *dev, unsigned char *buf, u32 len) +{ + struct hbm_dma_ring_ctrl *ctrl = mei_dma_ring_ctrl(dev); + u32 dbuf_depth; + u32 rd_idx, rem, slots; + + if (WARN_ON(!ctrl)) + return; + + dev_dbg(dev->dev, "reading from dma %u bytes\n", len); + + if (!len) + return; + + dbuf_depth = dev->dr_dscr[DMA_DSCR_DEVICE].size >> 2; + rd_idx = READ_ONCE(ctrl->dbuf_rd_idx) & (dbuf_depth - 1); + slots = mei_data2slots(len); + + /* if buf is NULL we drop the packet by advancing the pointer.*/ + if (!buf) + goto out; + + if (rd_idx + slots > dbuf_depth) { + buf += mei_dma_copy_from(dev, buf, rd_idx, dbuf_depth - rd_idx); + rem = slots - (dbuf_depth - rd_idx); + rd_idx = 0; + } else { + rem = slots; + } + + mei_dma_copy_from(dev, buf, rd_idx, rem); +out: + WRITE_ONCE(ctrl->dbuf_rd_idx, ctrl->dbuf_rd_idx + slots); +} diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 4f09bbcdbc2a..acbccb8dba34 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -206,6 +206,7 @@ enum mei_cl_disconnect_status { * @dma_ring: message is on dma ring * @internal: message is internal * @msg_complete: last packet of the message + * @extension: extension of the header */ struct mei_msg_hdr { u32 me_addr:8; @@ -215,8 +216,11 @@ struct mei_msg_hdr { u32 dma_ring:1; u32 internal:1; u32 msg_complete:1; + u32 extension[0]; } __packed; +#define MEI_MSG_HDR_MAX 2 + struct mei_bus_message { u8 hbm_cmd; u8 data[0]; diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 4888ebc076b7..eb026e2a0537 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -151,7 +151,7 @@ int mei_reset(struct mei_device *dev) mei_hbm_reset(dev); - dev->rd_msg_hdr = 0; + memset(dev->rd_msg_hdr, 0, sizeof(dev->rd_msg_hdr)); if (ret) { dev_err(dev->dev, "hw_reset failed ret = %d\n", ret); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 5a661cbdf2ae..055c2d89b310 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -75,6 +75,8 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl, */ static void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr) { + if (hdr->dma_ring) + mei_dma_ring_read(dev, NULL, hdr->extension[0]); /* * no need to check for size as it is guarantied * that length fits into rd_msg_buf @@ -100,6 +102,7 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_device *dev = cl->dev; struct mei_cl_cb *cb; size_t buf_sz; + u32 length; cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list); if (!cb) { @@ -119,25 +122,31 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl, goto discard; } - buf_sz = mei_hdr->length + cb->buf_idx; + length = mei_hdr->dma_ring ? mei_hdr->extension[0] : mei_hdr->length; + + buf_sz = length + cb->buf_idx; /* catch for integer overflow */ if (buf_sz < cb->buf_idx) { cl_err(dev, cl, "message is too big len %d idx %zu\n", - mei_hdr->length, cb->buf_idx); + length, cb->buf_idx); cb->status = -EMSGSIZE; goto discard; } if (cb->buf.size < buf_sz) { cl_dbg(dev, cl, "message overflow. size %zu len %d idx %zu\n", - cb->buf.size, mei_hdr->length, cb->buf_idx); + cb->buf.size, length, cb->buf_idx); cb->status = -EMSGSIZE; goto discard; } + if (mei_hdr->dma_ring) + mei_dma_ring_read(dev, cb->buf.data + cb->buf_idx, length); + + /* for DMA read 0 length to generate an interrupt to the device */ mei_read_slots(dev, cb->buf.data + cb->buf_idx, mei_hdr->length); - cb->buf_idx += mei_hdr->length; + cb->buf_idx += length; if (mei_hdr->msg_complete) { cl_dbg(dev, cl, "completed read length = %zu\n", cb->buf_idx); @@ -247,6 +256,9 @@ static inline int hdr_is_valid(u32 msg_hdr) if (!msg_hdr || mei_hdr->reserved) return -EBADMSG; + if (mei_hdr->dma_ring && mei_hdr->length != MEI_SLOT_SIZE) + return -EBADMSG; + return 0; } @@ -267,20 +279,20 @@ int mei_irq_read_handler(struct mei_device *dev, struct mei_cl *cl; int ret; - if (!dev->rd_msg_hdr) { - dev->rd_msg_hdr = mei_read_hdr(dev); + if (!dev->rd_msg_hdr[0]) { + dev->rd_msg_hdr[0] = mei_read_hdr(dev); (*slots)--; dev_dbg(dev->dev, "slots =%08x.\n", *slots); - ret = hdr_is_valid(dev->rd_msg_hdr); + ret = hdr_is_valid(dev->rd_msg_hdr[0]); if (ret) { dev_err(dev->dev, "corrupted message header 0x%08X\n", - dev->rd_msg_hdr); + dev->rd_msg_hdr[0]); goto end; } } - mei_hdr = (struct mei_msg_hdr *)&dev->rd_msg_hdr; + mei_hdr = (struct mei_msg_hdr *)dev->rd_msg_hdr; dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); if (mei_slots2data(*slots) < mei_hdr->length) { @@ -291,6 +303,12 @@ int mei_irq_read_handler(struct mei_device *dev, goto end; } + if (mei_hdr->dma_ring) { + dev->rd_msg_hdr[1] = mei_read_hdr(dev); + (*slots)--; + mei_hdr->length = 0; + } + /* HBM message */ if (hdr_is_hbm(mei_hdr)) { ret = mei_hbm_dispatch(dev, mei_hdr); @@ -324,7 +342,7 @@ int mei_irq_read_handler(struct mei_device *dev, goto reset_slots; } dev_err(dev->dev, "no destination client found 0x%08X\n", - dev->rd_msg_hdr); + dev->rd_msg_hdr[0]); ret = -EBADMSG; goto end; } @@ -334,9 +352,8 @@ int mei_irq_read_handler(struct mei_device *dev, reset_slots: /* reset the number of slots and header */ + memset(dev->rd_msg_hdr, 0, sizeof(dev->rd_msg_hdr)); *slots = mei_count_full_read_slots(dev); - dev->rd_msg_hdr = 0; - if (*slots == -EOVERFLOW) { /* overflow - reset */ dev_err(dev->dev, "resetting due to slots overflow.\n"); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 033b5eff8e59..bfd181fbd90c 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -497,7 +497,7 @@ struct mei_device { #endif /* CONFIG_PM */ unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; - u32 rd_msg_hdr; + u32 rd_msg_hdr[MEI_MSG_HDR_MAX]; /* write buffer */ bool hbuf_is_ready; @@ -598,6 +598,7 @@ int mei_dmam_ring_alloc(struct mei_device *dev); void mei_dmam_ring_free(struct mei_device *dev); bool mei_dma_ring_is_allocated(struct mei_device *dev); void mei_dma_ring_reset(struct mei_device *dev); +void mei_dma_ring_read(struct mei_device *dev, unsigned char *buf, u32 len); /* * MEI interrupt functions prototype -- cgit v1.2.3 From c30362cc326ac5c3d4e6c96aa8f68dbd86955489 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 22 Nov 2018 13:11:40 +0200 Subject: mei: dma ring: implement transmit flow Implement a circular buffer on allocated system memory. Read and write indices are stored on the control block which is also shared between the device and the host. Two new functions are exported from the DMA module: mei_dma_ring_write, and mei_dma_ring_empty_slots. The former simply copy a packet on the TX DMA circular buffer and later, returns the number of empty slots on the TX DMA circular buffer. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 64 +++++++++++++++++++++++++------- drivers/misc/mei/dma-ring.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ drivers/misc/mei/mei_dev.h | 2 + 3 files changed, 142 insertions(+), 13 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 5d15501af313..1fc8ea0f519b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1558,10 +1558,13 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_msg_hdr mei_hdr; size_t hdr_len = sizeof(mei_hdr); size_t len; - size_t hbuf_len; + size_t hbuf_len, dr_len; int hbuf_slots; + u32 dr_slots; + u32 dma_len; int rets; bool first_chunk; + const void *data; if (WARN_ON(!cl || !cl->dev)) return -ENODEV; @@ -1582,6 +1585,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, } len = buf->size - cb->buf_idx; + data = buf->data + cb->buf_idx; hbuf_slots = mei_hbuf_empty_slots(dev); if (hbuf_slots < 0) { rets = -EOVERFLOW; @@ -1589,6 +1593,8 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, } hbuf_len = mei_slots2data(hbuf_slots); + dr_slots = mei_dma_ring_empty_slots(dev); + dr_len = mei_slots2data(dr_slots); mei_msg_hdr_init(&mei_hdr, cb); @@ -1599,23 +1605,33 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, if (len + hdr_len <= hbuf_len) { mei_hdr.length = len; mei_hdr.msg_complete = 1; + } else if (dr_slots && hbuf_len >= hdr_len + sizeof(dma_len)) { + mei_hdr.dma_ring = 1; + if (len > dr_len) + len = dr_len; + else + mei_hdr.msg_complete = 1; + + mei_hdr.length = sizeof(dma_len); + dma_len = len; + data = &dma_len; } else if ((u32)hbuf_slots == mei_hbuf_depth(dev)) { - mei_hdr.length = hbuf_len - hdr_len; + len = hbuf_len - hdr_len; + mei_hdr.length = len; } else { return 0; } - cl_dbg(dev, cl, "buf: size = %zu idx = %zu\n", - cb->buf.size, cb->buf_idx); + if (mei_hdr.dma_ring) + mei_dma_ring_write(dev, buf->data + cb->buf_idx, len); - rets = mei_write_message(dev, &mei_hdr, hdr_len, - buf->data + cb->buf_idx, mei_hdr.length); + rets = mei_write_message(dev, &mei_hdr, hdr_len, data, mei_hdr.length); if (rets) goto err; cl->status = 0; cl->writing_state = MEI_WRITING; - cb->buf_idx += mei_hdr.length; + cb->buf_idx += len; if (first_chunk) { if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) { @@ -1650,11 +1666,13 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb) struct mei_msg_data *buf; struct mei_msg_hdr mei_hdr; size_t hdr_len = sizeof(mei_hdr); - size_t len; - size_t hbuf_len; + size_t len, hbuf_len, dr_len; int hbuf_slots; + u32 dr_slots; + u32 dma_len; ssize_t rets; bool blocking; + const void *data; if (WARN_ON(!cl || !cl->dev)) return -ENODEV; @@ -1666,10 +1684,12 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb) buf = &cb->buf; len = buf->size; - blocking = cb->blocking; cl_dbg(dev, cl, "len=%zd\n", len); + blocking = cb->blocking; + data = buf->data; + rets = pm_runtime_get(dev->dev); if (rets < 0 && rets != -EINPROGRESS) { pm_runtime_put_noidle(dev->dev); @@ -1706,16 +1726,32 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb) } hbuf_len = mei_slots2data(hbuf_slots); + dr_slots = mei_dma_ring_empty_slots(dev); + dr_len = mei_slots2data(dr_slots); if (len + hdr_len <= hbuf_len) { mei_hdr.length = len; mei_hdr.msg_complete = 1; + } else if (dr_slots && hbuf_len >= hdr_len + sizeof(dma_len)) { + mei_hdr.dma_ring = 1; + if (len > dr_len) + len = dr_len; + else + mei_hdr.msg_complete = 1; + + mei_hdr.length = sizeof(dma_len); + dma_len = len; + data = &dma_len; } else { - mei_hdr.length = hbuf_len - hdr_len; + len = hbuf_len - hdr_len; + mei_hdr.length = len; } + if (mei_hdr.dma_ring) + mei_dma_ring_write(dev, buf->data, len); + rets = mei_write_message(dev, &mei_hdr, hdr_len, - buf->data, mei_hdr.length); + data, mei_hdr.length); if (rets) goto err; @@ -1724,7 +1760,9 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb) goto err; cl->writing_state = MEI_WRITING; - cb->buf_idx = mei_hdr.length; + cb->buf_idx = len; + /* restore return value */ + len = buf->size; out: if (mei_hdr.msg_complete) diff --git a/drivers/misc/mei/dma-ring.c b/drivers/misc/mei/dma-ring.c index a0c40925049a..795641b82181 100644 --- a/drivers/misc/mei/dma-ring.c +++ b/drivers/misc/mei/dma-ring.c @@ -138,6 +138,26 @@ static size_t mei_dma_copy_from(struct mei_device *dev, unsigned char *buf, return b_n; } +/** + * mei_dma_copy_to() - copy to a buffer to the dma ring + * @dev: mei device + * @buf: data buffer + * @offset: offset in slots. + * @n: number of slots to copy. + */ +static size_t mei_dma_copy_to(struct mei_device *dev, unsigned char *buf, + u32 offset, u32 n) +{ + unsigned char *hbuf = dev->dr_dscr[DMA_DSCR_HOST].vaddr; + + size_t b_offset = offset << 2; + size_t b_n = n << 2; + + memcpy(hbuf + b_offset, buf, b_n); + + return b_n; +} + /** * mei_dma_ring_read() - read data from the ring * @dev: mei device @@ -178,3 +198,72 @@ void mei_dma_ring_read(struct mei_device *dev, unsigned char *buf, u32 len) out: WRITE_ONCE(ctrl->dbuf_rd_idx, ctrl->dbuf_rd_idx + slots); } + +static inline u32 mei_dma_ring_hbuf_depth(struct mei_device *dev) +{ + return dev->dr_dscr[DMA_DSCR_HOST].size >> 2; +} + +/** + * mei_dma_ring_empty_slots() - calaculate number of empty slots in dma ring + * @dev: mei_device + * + * Return: number of empty slots + */ +u32 mei_dma_ring_empty_slots(struct mei_device *dev) +{ + struct hbm_dma_ring_ctrl *ctrl = mei_dma_ring_ctrl(dev); + u32 wr_idx, rd_idx, hbuf_depth, empty; + + if (!mei_dma_ring_is_allocated(dev)) + return 0; + + if (WARN_ON(!ctrl)) + return 0; + + /* easier to work in slots */ + hbuf_depth = mei_dma_ring_hbuf_depth(dev); + rd_idx = READ_ONCE(ctrl->hbuf_rd_idx); + wr_idx = READ_ONCE(ctrl->hbuf_wr_idx); + + if (rd_idx > wr_idx) + empty = rd_idx - wr_idx; + else + empty = hbuf_depth - (wr_idx - rd_idx); + + return empty; +} + +/** + * mei_dma_ring_write - write data to dma ring host buffer + * + * @dev: mei_device + * @buf: data will be written + * @len: data length + */ +void mei_dma_ring_write(struct mei_device *dev, unsigned char *buf, u32 len) +{ + struct hbm_dma_ring_ctrl *ctrl = mei_dma_ring_ctrl(dev); + u32 hbuf_depth; + u32 wr_idx, rem, slots; + + if (WARN_ON(!ctrl)) + return; + + dev_dbg(dev->dev, "writing to dma %u bytes\n", len); + hbuf_depth = mei_dma_ring_hbuf_depth(dev); + wr_idx = READ_ONCE(ctrl->hbuf_wr_idx) & (hbuf_depth - 1); + slots = mei_data2slots(len); + + if (wr_idx + slots > hbuf_depth) { + buf += mei_dma_copy_to(dev, buf, wr_idx, hbuf_depth - wr_idx); + rem = slots - (hbuf_depth - wr_idx); + wr_idx = 0; + } else { + rem = slots; + } + + mei_dma_copy_to(dev, buf, wr_idx, rem); + + WRITE_ONCE(ctrl->hbuf_wr_idx, ctrl->hbuf_wr_idx + slots); +} diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index bfd181fbd90c..685b78ce30a5 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -599,6 +599,8 @@ void mei_dmam_ring_free(struct mei_device *dev); bool mei_dma_ring_is_allocated(struct mei_device *dev); void mei_dma_ring_reset(struct mei_device *dev); void mei_dma_ring_read(struct mei_device *dev, unsigned char *buf, u32 len); +void mei_dma_ring_write(struct mei_device *dev, unsigned char *buf, u32 len); +u32 mei_dma_ring_empty_slots(struct mei_device *dev); /* * MEI interrupt functions prototype -- cgit v1.2.3 From d2227583dc711443a6fa7971ea02812ebc1490f5 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 22 Nov 2018 13:11:41 +0200 Subject: mei: bump hbm version to 2.1 Bump HBM version to 2.1 to indicate DMA transfer support. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index acbccb8dba34..2b7f7677f8cc 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -35,7 +35,7 @@ /* * MEI Version */ -#define HBM_MINOR_VERSION 0 +#define HBM_MINOR_VERSION 1 #define HBM_MAJOR_VERSION 2 /* -- cgit v1.2.3 From 1dbfe7f23bdb7238c72d8efcffcd75280ff71d20 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 22 Nov 2018 13:11:42 +0200 Subject: mei: me: mark CNP devices as having dma support Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index ea4e152270a3..73ace2d59dea 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -98,9 +98,9 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP_4, MEI_ME_PCH8_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)}, /* required last entry */ -- cgit v1.2.3 From 97a64ba77db12e3f33680fc2540453c35b3681f7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 26 Nov 2018 11:12:29 +0300 Subject: misc/pvpanic: fix a NULL vs IS_ERR() check The devm_ioremap_resource() function doesn't return NULL, it returns error pointers. Fixes: 46f934c9a12f ("misc/pvpanic: add support to get pvpanic device info FDT") Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c index 01241ec6a5cd..595ac065b401 100644 --- a/drivers/misc/pvpanic.c +++ b/drivers/misc/pvpanic.c @@ -140,8 +140,8 @@ static int pvpanic_mmio_probe(struct platform_device *pdev) return -EINVAL; base = devm_ioremap_resource(&pdev->dev, mem); - if (base == NULL) - return -EFAULT; + if (IS_ERR(base)) + return PTR_ERR(base); atomic_notifier_chain_register(&panic_notifier_list, &pvpanic_panic_nb); -- cgit v1.2.3 From 55949c7e75ba535effd6965e47f705f173547dea Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 16 Nov 2018 16:11:02 -0600 Subject: misc: cxl: Use device_type helpers to access the node type Remove directly accessing device_node.type pointer and use the accessors instead. This will eventually allow removing the type pointer. Cc: Frederic Barrat Cc: Arnd Bergmann Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Rob Herring Acked-by: Andrew Donnellan Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cxl/pci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index b66d832d3233..c79ba1c699ad 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -1718,7 +1718,6 @@ int cxl_slot_is_switched(struct pci_dev *dev) { struct device_node *np; int depth = 0; - const __be32 *prop; if (!(np = pci_device_to_OF_node(dev))) { pr_err("cxl: np = NULL\n"); @@ -1727,8 +1726,7 @@ int cxl_slot_is_switched(struct pci_dev *dev) of_node_get(np); while (np) { np = of_get_next_parent(np); - prop = of_get_property(np, "device_type", NULL); - if (!prop || strcmp((char *)prop, "pciex")) + if (!of_node_is_type(np, "pciex")) break; depth++; } -- cgit v1.2.3 From 9ccb645683ef46e3c52c12c088a368baa58447d4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 24 Nov 2018 12:34:10 +0000 Subject: altera-stapl: check for a null key before strcasecmp'ing it Currently the null check on key is occurring after the strcasecmp on the key, hence there is a potential null pointer dereference on key. Fix this by checking if key is null first. Also replace the == 0 check on strcasecmp with just the ! operator. Detected by CoverityScan, CID#1248787 ("Dereference before null check") Fixes: fa766c9be58b ("[media] Altera FPGA firmware download module") Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/misc/altera-stapl/altera.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c index ef83a9078646..d2ed3b9728b7 100644 --- a/drivers/misc/altera-stapl/altera.c +++ b/drivers/misc/altera-stapl/altera.c @@ -2176,8 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size, key_ptr = &p[note_strings + get_unaligned_be32( &p[note_table + (8 * i)])]; - if ((strncasecmp(key, key_ptr, strlen(key_ptr)) == 0) && - (key != NULL)) { + if (key && !strncasecmp(key, key_ptr, strlen(key_ptr))) { status = 0; value_ptr = &p[note_strings + -- cgit v1.2.3 From eb30abeedee76c04bdf41c6d88545472c11a5632 Mon Sep 17 00:00:00 2001 From: Peng Hao Date: Fri, 16 Nov 2018 19:13:26 +0800 Subject: misc/pvpanic: resolve compile errors for arch=um Resolve compile error for arch=um pvpanic.c:(.text+0xb6): undefined reference to `devm_ioremap_resource' Signed-off-by: Peng Hao Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 642626ac1df1..f417b06e11c5 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -515,7 +515,7 @@ config MISC_RTSX config PVPANIC tristate "pvpanic device support" - depends on ACPI || OF + depends on HAS_IOMEM && (ACPI || OF) help This driver provides support for the pvpanic device. pvpanic is a paravirtualized device provided by QEMU; it lets a virtual machine -- cgit v1.2.3 From f8a70d8b889f180e6860cb1f85fed43d37844c5a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 3 Dec 2018 17:52:19 +0300 Subject: misc: vexpress: Off by one in vexpress_syscfg_exec() The > comparison should be >= to prevent reading beyond the end of the func->template[] array. (The func->template array is allocated in vexpress_syscfg_regmap_init() and it has func->num_templates elements.) Fixes: 974cc7b93441 ("mfd: vexpress: Define the device as MFD cells") Signed-off-by: Dan Carpenter Acked-by: Sudeep Holla Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vexpress-syscfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c index 6c3591cdf855..a3c6c773d9dc 100644 --- a/drivers/misc/vexpress-syscfg.c +++ b/drivers/misc/vexpress-syscfg.c @@ -61,7 +61,7 @@ static int vexpress_syscfg_exec(struct vexpress_syscfg_func *func, int tries; long timeout; - if (WARN_ON(index > func->num_templates)) + if (WARN_ON(index >= func->num_templates)) return -EINVAL; command = readl(syscfg->base + SYS_CFGCTRL); -- cgit v1.2.3 From 2796b43feeeaf2d74998e42d1fddcefed6955f54 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Sat, 1 Dec 2018 12:05:30 -0500 Subject: misc: remove GENWQE_DEBUGFS_RO() We already have the DEFINE_SHOW_ATTRIBUTE.There is no need to define such a macro,so remove GENWQE_DEBUGFS_RO.Also use DEFINE_SHOW_ATTRIBUTE to simplify some code. Signed-off-by: Yangtao Li Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_debugfs.c | 85 +++++++++++++++--------------------- drivers/misc/mic/card/mic_debugfs.c | 24 ++-------- drivers/misc/mic/cosm/cosm_debugfs.c | 39 ++++------------- drivers/misc/mic/host/mic_debugfs.c | 62 +++----------------------- drivers/misc/mic/scif/scif_debugfs.c | 44 +++---------------- drivers/misc/mic/vop/vop_debugfs.c | 40 ++--------------- drivers/misc/ti-st/st_kim.c | 34 +++------------ drivers/misc/vmw_balloon.c | 13 +----- 8 files changed, 73 insertions(+), 268 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/genwqe/card_debugfs.c b/drivers/misc/genwqe/card_debugfs.c index c6b82f09b3ba..7c713e01d198 100644 --- a/drivers/misc/genwqe/card_debugfs.c +++ b/drivers/misc/genwqe/card_debugfs.c @@ -33,19 +33,6 @@ #include "card_base.h" #include "card_ddcb.h" -#define GENWQE_DEBUGFS_RO(_name, _showfn) \ - static int genwqe_debugfs_##_name##_open(struct inode *inode, \ - struct file *file) \ - { \ - return single_open(file, _showfn, inode->i_private); \ - } \ - static const struct file_operations genwqe_##_name##_fops = { \ - .open = genwqe_debugfs_##_name##_open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - } - static void dbg_uidn_show(struct seq_file *s, struct genwqe_reg *regs, int entries) { @@ -87,26 +74,26 @@ static int curr_dbg_uidn_show(struct seq_file *s, void *unused, int uid) return 0; } -static int genwqe_curr_dbg_uid0_show(struct seq_file *s, void *unused) +static int curr_dbg_uid0_show(struct seq_file *s, void *unused) { return curr_dbg_uidn_show(s, unused, 0); } -GENWQE_DEBUGFS_RO(curr_dbg_uid0, genwqe_curr_dbg_uid0_show); +DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid0); -static int genwqe_curr_dbg_uid1_show(struct seq_file *s, void *unused) +static int curr_dbg_uid1_show(struct seq_file *s, void *unused) { return curr_dbg_uidn_show(s, unused, 1); } -GENWQE_DEBUGFS_RO(curr_dbg_uid1, genwqe_curr_dbg_uid1_show); +DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid1); -static int genwqe_curr_dbg_uid2_show(struct seq_file *s, void *unused) +static int curr_dbg_uid2_show(struct seq_file *s, void *unused) { return curr_dbg_uidn_show(s, unused, 2); } -GENWQE_DEBUGFS_RO(curr_dbg_uid2, genwqe_curr_dbg_uid2_show); +DEFINE_SHOW_ATTRIBUTE(curr_dbg_uid2); static int prev_dbg_uidn_show(struct seq_file *s, void *unused, int uid) { @@ -116,28 +103,28 @@ static int prev_dbg_uidn_show(struct seq_file *s, void *unused, int uid) return 0; } -static int genwqe_prev_dbg_uid0_show(struct seq_file *s, void *unused) +static int prev_dbg_uid0_show(struct seq_file *s, void *unused) { return prev_dbg_uidn_show(s, unused, 0); } -GENWQE_DEBUGFS_RO(prev_dbg_uid0, genwqe_prev_dbg_uid0_show); +DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid0); -static int genwqe_prev_dbg_uid1_show(struct seq_file *s, void *unused) +static int prev_dbg_uid1_show(struct seq_file *s, void *unused) { return prev_dbg_uidn_show(s, unused, 1); } -GENWQE_DEBUGFS_RO(prev_dbg_uid1, genwqe_prev_dbg_uid1_show); +DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid1); -static int genwqe_prev_dbg_uid2_show(struct seq_file *s, void *unused) +static int prev_dbg_uid2_show(struct seq_file *s, void *unused) { return prev_dbg_uidn_show(s, unused, 2); } -GENWQE_DEBUGFS_RO(prev_dbg_uid2, genwqe_prev_dbg_uid2_show); +DEFINE_SHOW_ATTRIBUTE(prev_dbg_uid2); -static int genwqe_curr_regs_show(struct seq_file *s, void *unused) +static int curr_regs_show(struct seq_file *s, void *unused) { struct genwqe_dev *cd = s->private; unsigned int i; @@ -164,9 +151,9 @@ static int genwqe_curr_regs_show(struct seq_file *s, void *unused) return 0; } -GENWQE_DEBUGFS_RO(curr_regs, genwqe_curr_regs_show); +DEFINE_SHOW_ATTRIBUTE(curr_regs); -static int genwqe_prev_regs_show(struct seq_file *s, void *unused) +static int prev_regs_show(struct seq_file *s, void *unused) { struct genwqe_dev *cd = s->private; unsigned int i; @@ -188,9 +175,9 @@ static int genwqe_prev_regs_show(struct seq_file *s, void *unused) return 0; } -GENWQE_DEBUGFS_RO(prev_regs, genwqe_prev_regs_show); +DEFINE_SHOW_ATTRIBUTE(prev_regs); -static int genwqe_jtimer_show(struct seq_file *s, void *unused) +static int jtimer_show(struct seq_file *s, void *unused) { struct genwqe_dev *cd = s->private; unsigned int vf_num; @@ -209,9 +196,9 @@ static int genwqe_jtimer_show(struct seq_file *s, void *unused) return 0; } -GENWQE_DEBUGFS_RO(jtimer, genwqe_jtimer_show); +DEFINE_SHOW_ATTRIBUTE(jtimer); -static int genwqe_queue_working_time_show(struct seq_file *s, void *unused) +static int queue_working_time_show(struct seq_file *s, void *unused) { struct genwqe_dev *cd = s->private; unsigned int vf_num; @@ -227,9 +214,9 @@ static int genwqe_queue_working_time_show(struct seq_file *s, void *unused) return 0; } -GENWQE_DEBUGFS_RO(queue_working_time, genwqe_queue_working_time_show); +DEFINE_SHOW_ATTRIBUTE(queue_working_time); -static int genwqe_ddcb_info_show(struct seq_file *s, void *unused) +static int ddcb_info_show(struct seq_file *s, void *unused) { struct genwqe_dev *cd = s->private; unsigned int i; @@ -300,9 +287,9 @@ static int genwqe_ddcb_info_show(struct seq_file *s, void *unused) return 0; } -GENWQE_DEBUGFS_RO(ddcb_info, genwqe_ddcb_info_show); +DEFINE_SHOW_ATTRIBUTE(ddcb_info); -static int genwqe_info_show(struct seq_file *s, void *unused) +static int info_show(struct seq_file *s, void *unused) { struct genwqe_dev *cd = s->private; u64 app_id, slu_id, bitstream = -1; @@ -335,7 +322,7 @@ static int genwqe_info_show(struct seq_file *s, void *unused) return 0; } -GENWQE_DEBUGFS_RO(info, genwqe_info_show); +DEFINE_SHOW_ATTRIBUTE(info); int genwqe_init_debugfs(struct genwqe_dev *cd) { @@ -356,14 +343,14 @@ int genwqe_init_debugfs(struct genwqe_dev *cd) /* non privileged interfaces are done here */ file = debugfs_create_file("ddcb_info", S_IRUGO, root, cd, - &genwqe_ddcb_info_fops); + &ddcb_info_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("info", S_IRUGO, root, cd, - &genwqe_info_fops); + &info_fops); if (!file) { ret = -ENOMEM; goto err1; @@ -396,56 +383,56 @@ int genwqe_init_debugfs(struct genwqe_dev *cd) } file = debugfs_create_file("curr_regs", S_IRUGO, root, cd, - &genwqe_curr_regs_fops); + &curr_regs_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("curr_dbg_uid0", S_IRUGO, root, cd, - &genwqe_curr_dbg_uid0_fops); + &curr_dbg_uid0_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("curr_dbg_uid1", S_IRUGO, root, cd, - &genwqe_curr_dbg_uid1_fops); + &curr_dbg_uid1_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("curr_dbg_uid2", S_IRUGO, root, cd, - &genwqe_curr_dbg_uid2_fops); + &curr_dbg_uid2_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("prev_regs", S_IRUGO, root, cd, - &genwqe_prev_regs_fops); + &prev_regs_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("prev_dbg_uid0", S_IRUGO, root, cd, - &genwqe_prev_dbg_uid0_fops); + &prev_dbg_uid0_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("prev_dbg_uid1", S_IRUGO, root, cd, - &genwqe_prev_dbg_uid1_fops); + &prev_dbg_uid1_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("prev_dbg_uid2", S_IRUGO, root, cd, - &genwqe_prev_dbg_uid2_fops); + &prev_dbg_uid2_fops); if (!file) { ret = -ENOMEM; goto err1; @@ -463,14 +450,14 @@ int genwqe_init_debugfs(struct genwqe_dev *cd) } file = debugfs_create_file("jobtimer", S_IRUGO, root, cd, - &genwqe_jtimer_fops); + &jtimer_fops); if (!file) { ret = -ENOMEM; goto err1; } file = debugfs_create_file("queue_working_time", S_IRUGO, root, cd, - &genwqe_queue_working_time_fops); + &queue_working_time_fops); if (!file) { ret = -ENOMEM; goto err1; diff --git a/drivers/misc/mic/card/mic_debugfs.c b/drivers/misc/mic/card/mic_debugfs.c index 421b3d7911df..7a4140874888 100644 --- a/drivers/misc/mic/card/mic_debugfs.c +++ b/drivers/misc/mic/card/mic_debugfs.c @@ -37,9 +37,9 @@ static struct dentry *mic_dbg; /** - * mic_intr_test - Send interrupts to host. + * mic_intr_show - Send interrupts to host. */ -static int mic_intr_test(struct seq_file *s, void *unused) +static int mic_intr_show(struct seq_file *s, void *unused) { struct mic_driver *mdrv = s->private; struct mic_device *mdev = &mdrv->mdev; @@ -56,23 +56,7 @@ static int mic_intr_test(struct seq_file *s, void *unused) return 0; } -static int mic_intr_test_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_intr_test, inode->i_private); -} - -static int mic_intr_test_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations intr_test_ops = { - .owner = THIS_MODULE, - .open = mic_intr_test_open, - .read = seq_read, - .llseek = seq_lseek, - .release = mic_intr_test_release -}; +DEFINE_SHOW_ATTRIBUTE(mic_intr); /** * mic_create_card_debug_dir - Initialize MIC debugfs entries. @@ -91,7 +75,7 @@ void __init mic_create_card_debug_dir(struct mic_driver *mdrv) } d = debugfs_create_file("intr_test", 0444, mdrv->dbg_dir, - mdrv, &intr_test_ops); + mdrv, &mic_intr_fops); if (!d) { dev_err(mdrv->dev, diff --git a/drivers/misc/mic/cosm/cosm_debugfs.c b/drivers/misc/mic/cosm/cosm_debugfs.c index 216cb3cd2fe3..71c216d0504d 100644 --- a/drivers/misc/mic/cosm/cosm_debugfs.c +++ b/drivers/misc/mic/cosm/cosm_debugfs.c @@ -28,12 +28,12 @@ static struct dentry *cosm_dbg; /** - * cosm_log_buf_show - Display MIC kernel log buffer + * log_buf_show - Display MIC kernel log buffer * * log_buf addr/len is read from System.map by user space * and populated in sysfs entries. */ -static int cosm_log_buf_show(struct seq_file *s, void *unused) +static int log_buf_show(struct seq_file *s, void *unused) { void __iomem *log_buf_va; int __iomem *log_buf_len_va; @@ -78,26 +78,15 @@ done: return 0; } -static int cosm_log_buf_open(struct inode *inode, struct file *file) -{ - return single_open(file, cosm_log_buf_show, inode->i_private); -} - -static const struct file_operations log_buf_ops = { - .owner = THIS_MODULE, - .open = cosm_log_buf_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release -}; +DEFINE_SHOW_ATTRIBUTE(log_buf); /** - * cosm_force_reset_show - Force MIC reset + * force_reset_show - Force MIC reset * * Invokes the force_reset COSM bus op instead of the standard reset * op in case a force reset of the MIC device is required */ -static int cosm_force_reset_show(struct seq_file *s, void *pos) +static int force_reset_show(struct seq_file *s, void *pos) { struct cosm_device *cdev = s->private; @@ -105,18 +94,7 @@ static int cosm_force_reset_show(struct seq_file *s, void *pos) return 0; } -static int cosm_force_reset_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, cosm_force_reset_show, inode->i_private); -} - -static const struct file_operations force_reset_ops = { - .owner = THIS_MODULE, - .open = cosm_force_reset_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release -}; +DEFINE_SHOW_ATTRIBUTE(force_reset); void cosm_create_debug_dir(struct cosm_device *cdev) { @@ -130,9 +108,10 @@ void cosm_create_debug_dir(struct cosm_device *cdev) if (!cdev->dbg_dir) return; - debugfs_create_file("log_buf", 0444, cdev->dbg_dir, cdev, &log_buf_ops); + debugfs_create_file("log_buf", 0444, cdev->dbg_dir, cdev, + &log_buf_fops); debugfs_create_file("force_reset", 0444, cdev->dbg_dir, cdev, - &force_reset_ops); + &force_reset_fops); } void cosm_delete_debug_dir(struct cosm_device *cdev) diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c index 0a9daba8bb5d..c6e3c764699f 100644 --- a/drivers/misc/mic/host/mic_debugfs.c +++ b/drivers/misc/mic/host/mic_debugfs.c @@ -54,23 +54,7 @@ static int mic_smpt_show(struct seq_file *s, void *pos) return 0; } -static int mic_smpt_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_smpt_show, inode->i_private); -} - -static int mic_smpt_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations smpt_file_ops = { - .owner = THIS_MODULE, - .open = mic_smpt_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = mic_smpt_debug_release -}; +DEFINE_SHOW_ATTRIBUTE(mic_smpt); static int mic_post_code_show(struct seq_file *s, void *pos) { @@ -81,23 +65,7 @@ static int mic_post_code_show(struct seq_file *s, void *pos) return 0; } -static int mic_post_code_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_post_code_show, inode->i_private); -} - -static int mic_post_code_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations post_code_ops = { - .owner = THIS_MODULE, - .open = mic_post_code_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = mic_post_code_debug_release -}; +DEFINE_SHOW_ATTRIBUTE(mic_post_code); static int mic_msi_irq_info_show(struct seq_file *s, void *pos) { @@ -143,24 +111,7 @@ static int mic_msi_irq_info_show(struct seq_file *s, void *pos) return 0; } -static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_msi_irq_info_show, inode->i_private); -} - -static int -mic_msi_irq_info_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations msi_irq_info_ops = { - .owner = THIS_MODULE, - .open = mic_msi_irq_info_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = mic_msi_irq_info_debug_release -}; +DEFINE_SHOW_ATTRIBUTE(mic_msi_irq_info); /** * mic_create_debug_dir - Initialize MIC debugfs entries. @@ -177,13 +128,14 @@ void mic_create_debug_dir(struct mic_device *mdev) if (!mdev->dbg_dir) return; - debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops); + debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, + &mic_smpt_fops); debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev, - &post_code_ops); + &mic_post_code_fops); debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev, - &msi_irq_info_ops); + &mic_msi_irq_info_fops); } /** diff --git a/drivers/misc/mic/scif/scif_debugfs.c b/drivers/misc/mic/scif/scif_debugfs.c index 6884dad97e17..cca5e980c710 100644 --- a/drivers/misc/mic/scif/scif_debugfs.c +++ b/drivers/misc/mic/scif/scif_debugfs.c @@ -24,7 +24,7 @@ /* Debugfs parent dir */ static struct dentry *scif_dbg; -static int scif_dev_test(struct seq_file *s, void *unused) +static int scif_dev_show(struct seq_file *s, void *unused) { int node; @@ -44,23 +44,7 @@ static int scif_dev_test(struct seq_file *s, void *unused) return 0; } -static int scif_dev_test_open(struct inode *inode, struct file *file) -{ - return single_open(file, scif_dev_test, inode->i_private); -} - -static int scif_dev_test_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations scif_dev_ops = { - .owner = THIS_MODULE, - .open = scif_dev_test_open, - .read = seq_read, - .llseek = seq_lseek, - .release = scif_dev_test_release -}; +DEFINE_SHOW_ATTRIBUTE(scif_dev); static void scif_display_window(struct scif_window *window, struct seq_file *s) { @@ -104,7 +88,7 @@ static void scif_display_all_windows(struct list_head *head, struct seq_file *s) } } -static int scif_rma_test(struct seq_file *s, void *unused) +static int scif_rma_show(struct seq_file *s, void *unused) { struct scif_endpt *ep; struct list_head *pos; @@ -123,23 +107,7 @@ static int scif_rma_test(struct seq_file *s, void *unused) return 0; } -static int scif_rma_test_open(struct inode *inode, struct file *file) -{ - return single_open(file, scif_rma_test, inode->i_private); -} - -static int scif_rma_test_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations scif_rma_ops = { - .owner = THIS_MODULE, - .open = scif_rma_test_open, - .read = seq_read, - .llseek = seq_lseek, - .release = scif_rma_test_release -}; +DEFINE_SHOW_ATTRIBUTE(scif_rma); void __init scif_init_debugfs(void) { @@ -150,8 +118,8 @@ void __init scif_init_debugfs(void) return; } - debugfs_create_file("scif_dev", 0444, scif_dbg, NULL, &scif_dev_ops); - debugfs_create_file("scif_rma", 0444, scif_dbg, NULL, &scif_rma_ops); + debugfs_create_file("scif_dev", 0444, scif_dbg, NULL, &scif_dev_fops); + debugfs_create_file("scif_rma", 0444, scif_dbg, NULL, &scif_rma_fops); debugfs_create_u8("en_msg_log", 0666, scif_dbg, &scif_info.en_msg_log); debugfs_create_u8("p2p_enable", 0666, scif_dbg, &scif_info.p2p_enable); } diff --git a/drivers/misc/mic/vop/vop_debugfs.c b/drivers/misc/mic/vop/vop_debugfs.c index ab43884e5cd7..2ccef52aca23 100644 --- a/drivers/misc/mic/vop/vop_debugfs.c +++ b/drivers/misc/mic/vop/vop_debugfs.c @@ -101,23 +101,7 @@ static int vop_dp_show(struct seq_file *s, void *pos) return 0; } -static int vop_dp_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, vop_dp_show, inode->i_private); -} - -static int vop_dp_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations dp_ops = { - .owner = THIS_MODULE, - .open = vop_dp_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = vop_dp_debug_release -}; +DEFINE_SHOW_ATTRIBUTE(vop_dp); static int vop_vdev_info_show(struct seq_file *s, void *unused) { @@ -194,23 +178,7 @@ static int vop_vdev_info_show(struct seq_file *s, void *unused) return 0; } -static int vop_vdev_info_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, vop_vdev_info_show, inode->i_private); -} - -static int vop_vdev_info_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations vdev_info_ops = { - .owner = THIS_MODULE, - .open = vop_vdev_info_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = vop_vdev_info_debug_release -}; +DEFINE_SHOW_ATTRIBUTE(vop_vdev_info); void vop_init_debugfs(struct vop_info *vi) { @@ -222,8 +190,8 @@ void vop_init_debugfs(struct vop_info *vi) pr_err("can't create debugfs dir vop\n"); return; } - debugfs_create_file("dp", 0444, vi->dbg, vi, &dp_ops); - debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vdev_info_ops); + debugfs_create_file("dp", 0444, vi->dbg, vi, &vop_dp_fops); + debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vop_vdev_info_fops); } void vop_exit_debugfs(struct vop_info *vi) diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 1874ac922166..e47abf173626 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -564,7 +564,7 @@ long st_kim_stop(void *kim_data) /* functions called from subsystems */ /* called when debugfs entry is read from */ -static int show_version(struct seq_file *s, void *unused) +static int version_show(struct seq_file *s, void *unused) { struct kim_data_s *kim_gdata = (struct kim_data_s *)s->private; seq_printf(s, "%04X %d.%d.%d\n", kim_gdata->version.full, @@ -573,7 +573,7 @@ static int show_version(struct seq_file *s, void *unused) return 0; } -static int show_list(struct seq_file *s, void *unused) +static int list_show(struct seq_file *s, void *unused) { struct kim_data_s *kim_gdata = (struct kim_data_s *)s->private; kim_st_list_protocols(kim_gdata->core_data, s); @@ -688,30 +688,8 @@ err: *core_data = NULL; } -static int kim_version_open(struct inode *i, struct file *f) -{ - return single_open(f, show_version, i->i_private); -} - -static int kim_list_open(struct inode *i, struct file *f) -{ - return single_open(f, show_list, i->i_private); -} - -static const struct file_operations version_debugfs_fops = { - /* version info */ - .open = kim_version_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -static const struct file_operations list_debugfs_fops = { - /* protocols info */ - .open = kim_list_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(version); +DEFINE_SHOW_ATTRIBUTE(list); /**********************************************************************/ /* functions called from platform device driver subsystem @@ -789,9 +767,9 @@ static int kim_probe(struct platform_device *pdev) } debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, - kim_gdata, &version_debugfs_fops); + kim_gdata, &version_fops); debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir, - kim_gdata, &list_debugfs_fops); + kim_gdata, &list_fops); return 0; err_sysfs_group: diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index 9b0b3fa4f836..e43cec7f3a86 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c @@ -1470,18 +1470,7 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset) return 0; } -static int vmballoon_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, vmballoon_debug_show, inode->i_private); -} - -static const struct file_operations vmballoon_debug_fops = { - .owner = THIS_MODULE, - .open = vmballoon_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(vmballoon_debug); static int __init vmballoon_debugfs_init(struct vmballoon *b) { -- cgit v1.2.3 From 4b4bdfe7d4a02a5c88ec242e3469cb81e00f1f34 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 29 Nov 2018 23:15:56 +0000 Subject: misc: ti-st: make array read_ver_cmd static, shrinks object size Don't populate the const array read_ver_cmd on the stack but instead make it static. Makes the object code smaller by 42 bytes: Before: text data bss dec hex filename 17262 6928 192 24382 5f3e drivers/misc/ti-st/st_kim.o After: text data bss dec hex filename 17156 6992 192 24340 5f14 drivers/misc/ti-st/st_kim.o (gcc version 8.2.0 x86_64) Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ti-st/st_kim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index e47abf173626..e7cfdbd1f66d 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -211,7 +211,7 @@ static void kim_int_recv(struct kim_data_s *kim_gdata, static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) { unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0; - const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 }; + static const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 }; long timeout; pr_debug("%s", __func__); -- cgit v1.2.3 From fdd669684655c07dacbdb0d753fd13833de69a33 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 12 Dec 2018 14:45:18 +0100 Subject: genwqe: Fix size check Calling the test program genwqe_cksum with the default buffer size of 2MB triggers the following kernel warning on s390: WARNING: CPU: 30 PID: 9311 at mm/page_alloc.c:3189 __alloc_pages_nodemask+0x45c/0xbe0 CPU: 30 PID: 9311 Comm: genwqe_cksum Kdump: loaded Not tainted 3.10.0-957.el7.s390x #1 task: 00000005e5d13980 ti: 00000005e7c6c000 task.ti: 00000005e7c6c000 Krnl PSW : 0704c00180000000 00000000002780ac (__alloc_pages_nodemask+0x45c/0xbe0) R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 EA:3 Krnl GPRS: 00000000002932b8 0000000000b73d7c 0000000000000010 0000000000000009 0000000000000041 00000005e7c6f9b8 0000000000000001 00000000000080d0 0000000000000000 0000000000b70500 0000000000000001 0000000000000000 0000000000b70528 00000000007682c0 0000000000277df2 00000005e7c6f9a0 Krnl Code: 000000000027809e: de7195001000 ed 1280(114,%r9),0(%r1) 00000000002780a4: a774fead brc 7,277dfe #00000000002780a8: a7f40001 brc 15,2780aa >00000000002780ac: 92011000 mvi 0(%r1),1 00000000002780b0: a7f4fea7 brc 15,277dfe 00000000002780b4: 9101c6b6 tm 1718(%r12),1 00000000002780b8: a784ff3a brc 8,277f2c 00000000002780bc: a7f4fe2e brc 15,277d18 Call Trace: ([<0000000000277df2>] __alloc_pages_nodemask+0x1a2/0xbe0) [<000000000013afae>] s390_dma_alloc+0xfe/0x310 [<000003ff8065f362>] __genwqe_alloc_consistent+0xfa/0x148 [genwqe_card] [<000003ff80658f7a>] genwqe_mmap+0xca/0x248 [genwqe_card] [<00000000002b2712>] mmap_region+0x4e2/0x778 [<00000000002b2c54>] do_mmap+0x2ac/0x3e0 [<0000000000292d7e>] vm_mmap_pgoff+0xd6/0x118 [<00000000002b081c>] SyS_mmap_pgoff+0xdc/0x268 [<00000000002b0a34>] SyS_old_mmap+0x8c/0xb0 [<000000000074e518>] sysc_tracego+0x14/0x1e [<000003ffacf87dc6>] 0x3ffacf87dc6 turns out the check in __genwqe_alloc_consistent uses "> MAX_ORDER" while the mm code uses ">= MAX_ORDER". Fix genwqe. Cc: stable@vger.kernel.org Signed-off-by: Christian Borntraeger Signed-off-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 3fcb9a2fe1c9..efe2fb72d54b 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -215,7 +215,7 @@ u32 genwqe_crc32(u8 *buff, size_t len, u32 init) void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size, dma_addr_t *dma_handle) { - if (get_order(size) > MAX_ORDER) + if (get_order(size) >= MAX_ORDER) return NULL; return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle, -- cgit v1.2.3 From 15b3048aeed8bf8232156456c884ae94ed52d6cd Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Tue, 4 Dec 2018 09:16:41 -0600 Subject: misc: mic: fix a DMA pool free failure In _scif_prog_signal(), a DMA pool is allocated if the MIC Coprocessor is not X100, i.e., the boolean variable 'x100' is false. This DMA pool will be freed eventually through the callback function scif_prog_signal_cb() with the parameter of 'status', which actually points to the start of DMA pool. Specifically, in scif_prog_signal_cb(), the 'ep' field and the 'src_dma_addr' field of 'status' are used to free the DMA pool by invoking dma_pool_free(). Given that 'status' points to the start address of the DMA pool, both 'status->ep' and 'status->src_dma_addr' are in the DMA pool. And so, the device has the permission to access them. Even worse, a malicious device can modify them. As a result, dma_pool_free() will not succeed. To avoid the above issue, this patch introduces a new data structure, i.e., scif_cb_arg, to store the arguments required by the call back function. A variable 'cb_arg' is allocated in _scif_prog_signal() to pass the arguments. 'cb_arg' will be freed after dma_pool_free() in scif_prog_signal_cb(). Signed-off-by: Wenwen Wang Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/scif/scif_fence.c | 22 +++++++++++++++++----- drivers/misc/mic/scif/scif_rma.h | 13 +++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mic/scif/scif_fence.c b/drivers/misc/mic/scif/scif_fence.c index 7bb929f05d85..2e7ce6ae9dd2 100644 --- a/drivers/misc/mic/scif/scif_fence.c +++ b/drivers/misc/mic/scif/scif_fence.c @@ -195,10 +195,11 @@ static inline void *scif_get_local_va(off_t off, struct scif_window *window) static void scif_prog_signal_cb(void *arg) { - struct scif_status *status = arg; + struct scif_cb_arg *cb_arg = arg; - dma_pool_free(status->ep->remote_dev->signal_pool, status, - status->src_dma_addr); + dma_pool_free(cb_arg->ep->remote_dev->signal_pool, cb_arg->status, + cb_arg->src_dma_addr); + kfree(cb_arg); } static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val) @@ -209,6 +210,7 @@ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val) bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1); struct dma_async_tx_descriptor *tx; struct scif_status *status = NULL; + struct scif_cb_arg *cb_arg = NULL; dma_addr_t src; dma_cookie_t cookie; int err; @@ -257,8 +259,16 @@ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val) goto dma_fail; } if (!x100) { + cb_arg = kmalloc(sizeof(*cb_arg), GFP_KERNEL); + if (!cb_arg) { + err = -ENOMEM; + goto dma_fail; + } + cb_arg->src_dma_addr = src; + cb_arg->status = status; + cb_arg->ep = ep; tx->callback = scif_prog_signal_cb; - tx->callback_param = status; + tx->callback_param = cb_arg; } cookie = tx->tx_submit(tx); if (dma_submit_error(cookie)) { @@ -270,9 +280,11 @@ static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val) dma_async_issue_pending(chan); return 0; dma_fail: - if (!x100) + if (!x100) { dma_pool_free(ep->remote_dev->signal_pool, status, src - offsetof(struct scif_status, val)); + kfree(cb_arg); + } alloc_fail: return err; } diff --git a/drivers/misc/mic/scif/scif_rma.h b/drivers/misc/mic/scif/scif_rma.h index fa6722279196..84af3033a473 100644 --- a/drivers/misc/mic/scif/scif_rma.h +++ b/drivers/misc/mic/scif/scif_rma.h @@ -205,6 +205,19 @@ struct scif_status { struct scif_endpt *ep; }; +/* + * struct scif_cb_arg - Stores the argument of the callback func + * + * @src_dma_addr: Source buffer DMA address + * @status: DMA status + * @ep: SCIF endpoint + */ +struct scif_cb_arg { + dma_addr_t src_dma_addr; + struct scif_status *status; + struct scif_endpt *ep; +}; + /* * struct scif_window - Registration Window for Self and Remote * -- cgit v1.2.3 From 8995fa1e1c9bcb76d407b860770e640b60ed8c76 Mon Sep 17 00:00:00 2001 From: Wen Yang Date: Mon, 10 Dec 2018 19:36:07 +0800 Subject: VMCI: Use memdup_user() rather than duplicating its implementation Reuse existing functionality from memdup_user() instead of keeping duplicate source code. This issue was detected by using the Coccinelle software. Signed-off-by: Wen Yang CC: Arnd Bergmann CC: Greg Kroah-Hartman CC: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vmw_vmci/vmci_host.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index edfffc9699ba..5da1f3e3f997 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -750,19 +750,10 @@ static int vmci_host_do_ctx_set_cpt_state(struct vmci_host_dev *vmci_host_dev, if (copy_from_user(&set_info, uptr, sizeof(set_info))) return -EFAULT; - cpt_buf = kmalloc(set_info.buf_size, GFP_KERNEL); - if (!cpt_buf) { - vmci_ioctl_err( - "cannot allocate memory to set cpt state (type=%d)\n", - set_info.cpt_type); - return -ENOMEM; - } - - if (copy_from_user(cpt_buf, (void __user *)(uintptr_t)set_info.cpt_buf, - set_info.buf_size)) { - retval = -EFAULT; - goto out; - } + cpt_buf = memdup_user((void __user *)(uintptr_t)set_info.cpt_buf, + set_info.buf_size); + if (IS_ERR(cpt_buf)) + return PTR_ERR(cpt_buf); cid = vmci_ctx_get_id(vmci_host_dev->context); set_info.result = vmci_ctx_set_chkpt_state(cid, set_info.cpt_type, @@ -770,7 +761,6 @@ static int vmci_host_do_ctx_set_cpt_state(struct vmci_host_dev *vmci_host_dev, retval = copy_to_user(uptr, &set_info, sizeof(set_info)) ? -EFAULT : 0; -out: kfree(cpt_buf); return retval; } -- cgit v1.2.3